我最近在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
的常规舞蹈?
答案 0 :(得分:1)
这种做法安全吗?这是否相当于[弱者]的平常舞蹈 自我],strongSelf =自我封闭内部?
是和否 - 捕获对象的方法也会保留对象。捕获的方法可以从实例访问任何内容,因此保留它是有道理的。
另一方面,捕获属性不会保留实例。
这是一个简短的片段,您可以在操场上粘贴以便自己查看:
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后立即被取消初始化。
答案 1 :(得分:1)
deinit
之前被处理掉(你绝对确定它会触发有限的次数和然后序列总是结束)。对于非反应性用例也是如此。 strongSelf
行为闭包只保留对对象的弱引用,在执行开始时将其绑定为强,然后在执行结束时释放强引用。