swift - 直接在闭包中捕获值时的内存语义
问题描述
我最近在objc.io的这篇文章中阅读了有关捕获列表的内容。我认为这是一个很好的提示,我开始使用它。
虽然没有完全澄清,但我假设以这种方式捕获时没有保留周期,因此您获得了捕获的强引用,但无需担心保留周期。
而且我意识到甚至可以捕获方法,而不仅仅是值:
.subscribe(onNext: { [showErrorAlert, populate] result in
switch result {
case .success(let book):
populate(book)
case .error(_):
showErrorAlert(L10n.errorExecutingOperation.localized)
}
})
我正在尝试查找与这种捕获方式相关的一些文档,但我找不到任何文档。这种做法安全吗?这是否等于闭包内的[weak self]
,的通常舞蹈?strongSelf = self
解决方案
这种做法安全吗?这是否等于闭包内的 [weak self], strongSelf = self 的通常舞蹈?
是和否 - 对象的捕获方法也会保留对象。捕获的方法可能正在访问实例中的任何内容,因此保留它是有意义的。
另一方面,捕获属性不会保留实例。
这是一个简短的片段,您可以粘贴到操场上亲自查看:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
class A {
let name: String
init(name: String) {
self.name = name
}
func a() {
print("Hello from \(name)")
}
func scheduleCaptured() {
print("Scheduling captured method")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { [a] in
a()
}
}
func scheduleCapturedVariable() {
print("Scheduling captured variable")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { [name] in
print("Hello from \(name)")
}
}
deinit {
print("\(name) deinit")
}
}
var a1: A? = A(name: "instance 1")
a1?.scheduleCapturedVariable()
var a2: A? = A(name: "instance 2")
a2?.scheduleCaptured()
a1 = nil
a2 = nil
输出是:
Scheduling captured variable
Scheduling captured method
instance 1 deinit
Hello from instance 1
Hello from instance 2
instance 2 deinit
您可以看到instance 2
在触发捕获的块之前不会取消初始化,而instance 1
在设置为 nil 后立即取消初始化。
推荐阅读
- ios - iOS 3DAnimations:旋转多个叠加视图时出现问题
- python - 在python中获取给定字符串的日期列表
- unity3d - 5赔后如何投放广告?统一安卓
- mongodb - mongodb查找具有相同键值的文档但不知道该值是什么
- java - 使用 Java 9 和更高版本替代默认包
- android - 如何为 putParcelableArrayList 使用通用列表?
- kdb - 删除无键表中多余的重复条目
- biztalk - 主机实例不断重启
- caching - 将 Hazelcast / Redis 隐藏在 REST 控制器后面是否有点矫枉过正?
- python - 如何从另一个容器中的容器执行脚本?