【发布时间】:2016-08-05 01:37:19
【问题描述】:
我正在像下面这样在关闭中试验保留周期
class Sample {
deinit {
print("Destroying Sample")
}
func additionOf(a: Int, b:Int) {
print("Addition is \(a + b)")
}
func closure() {
dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in
self?.additionOf(3, b: 3)
usleep(500)
self?.additionOf(3, b: 5)
}
}
}
稍后,我正在做
var sample : Sample? = Sample()
sample?.closure()
dispatch_async(dispatch_get_global_queue(0, 0)) {
usleep(100)
sample = nil
}
输出将是
Addition is 6
Destroying Sample
这是可以理解的,因为self 在执行self?.additionOf(3, b:5) 之前为零
如果我通过创建另一个引用 [weak self] 的变量来在闭包内进行更改,如下所示
dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.additionOf(3, b: 3)
usleep(500)
strongSelf.additionOf(3, b: 5)
}
这次的输出是
Addition is 6
Addition is 8
Destroying C
我的问题是为什么strongSelf 在sample = nil 之后不为零。是不是因为在sample = nil之前的闭包里面被捕获了
【问题讨论】:
-
当您设置
sample = nil时,您所做的就是解决对Sample的一个特别强的引用。但它对可能存在的任何其他强引用没有影响(例如strongSelf,它是在您执行sample = nil之前分配的)。在[weak self]闭包中执行strongSelf模式(有时被戏称为“strongSelf/weakSelf dance”)的全部目的是确保如果Sample在闭包开始时没有被释放,它将保持直到关闭完成。 -
@Rob:我想我理解但不是 100%。从 OP 开始,当关闭开始时,直到执行第一个
additionOf(3, b: 3)之前,Sample 还没有被释放。我仍然不明白为什么strongSelf没有改变,因为 self 为零。除非它被捕获在闭包内?? -
并不是被闭包“捕获”了。简单地说,闭包已经建立了对
Sample对象的新的第二个强引用。因此,当您致电var sample : Sample? = Sample()时,有一个强有力的参考。当代码遇到guard let strongSelf = self else ...时,即建立了第二个强引用,一共是两个强引用。当您在主线程上执行sample = nil时,还剩下一个强引用。只有当strongSelf超出范围时,才会解析这个最终的强引用并释放对象。
标签: memory-management swift2 closures weak-references strong-references