我为此使用的标题可能不是特别清楚,所以我希望工作的示例代码可以使您更清楚。
我面临的问题是,我的情况类似于以下代码:
import Foundation
class Test {
private var isInner = false {
didSet {
print("isInner: \(isInner)")
}
}
private func runClosure(closure: () -> ()) {
closure()
}
func callClosure() {
// Weak 1
runClosure { [weak self] in
self?.isInner = false
guard let strongSelf = self else { return }
// Can this [weak self] create problems?
// Weak 2
strongSelf.runClosure { [weak self] in
self?.isInner = true
}
}
}
}
let test = Test()
test.callClosure()
// The following is printed to the console
// isInner: false
// isInner: true
以上所有内容均按预期工作,这很好。
我担心的是
[weak self]
的第二次使用。虽然self
在函数开始时声明为弱( Weak1 ),但此后不久我将其设置为strongSelf
。我可以重用以前的
strongSelf
,但是所讨论的功能实际上可能是长时间运行的操作,并且有可能self可能超出 Weak1 和 Weak2 之间的范围。但是,已经提请我注意
Weak2
可能存在无效的可能性,这就是我希望通过这个问题来阐明的可能性。最终,所有弱点就是为self创建一个可选变量,因此我不知道有任何潜在的陷阱。此外,
strongSelf
执行期间, Weakself1 ,callClosure()
和 Weakself2 都指向相同的内存地址。 最佳答案
让我们一步一步地(逐行)
// Weak 1
runClosure { [weak self] in
第一行创建对目标对象的引用,巧合(或不巧合)的引用名为
self
。 self?.isInner = false
上面的代码利用了弱引用,对目标对象的生命周期没有影响。
guard let strongSelf = self else { return }
现在,此行确实创建了对目标对象的强大引用,这将使对象的生存期至少延长
strongSelf
的生存期。现在,取决于编译器的攻击性,strongSelf
可能会在通过此行(代码中的最后一个引用)之后或外部闭包完成执行时死亡。 // Can this [weak self] create problems?
// Weak 2
strongSelf.runClosure { [weak self] in
现在,这几乎与从外部封盖捕获的效果完全相同。它创建对可能已经释放的实例的引用(取决于
strongSelf
在这一点上是否仍然有效)。 self?.isInner = true
这是常规的可选用法,对目标寿命没有影响。
现在,假设
runClosure
异步运行,那么目标对象的寿命就不会超出预期(假设那里没有更强大的引用)了。总而言之,对象生存期取决于该对象存在的强引用的数量。一旦所有强引用都被销毁,该对象将被自动释放。在您的特定情况下,内部闭包很难捕获到已经很弱的引用,并且这不会影响目标对象的生命周期。唯一的参与者是
strongSelf
,它不迟于外部封盖销毁被销毁。