![](/img/trans.png)
[英]Does closure create a strong reference to an object that is created inside closure scope?
[英]convert the reference back to a strong one inside the closure, memory management, swift
我正在尝试关闭保留周期,如下所示
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)
之前是没有的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
我的问题是为什么在sample = nil
之后, strongSelf
不会出现问题。 是因为它在sample = nil
之前被捕获在闭包内
让我们考虑你的第二个例子:
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)
}
这是一种常见的模式,它有效地说“如果self
已被解除分配,立即return
,否则建立一个强大的参考, strongSelf
,并保持这个强大的参考,直到关闭完成。”
所以,在你的例子中,当这个调度块开始时self
不是nil
,所以一旦我们分配了strongSelf
来引用它,我们现在有两个强引用这个Sample
对象,原始sample
引用和这个新的strongSelf
引用里面这个关闭。
因此,当你的另一个线程删除它自己的强引用, sample
,到这个Sample
对象时(通过超出范围或通过显式设置sample
为nil
),这个strongSelf
强引用仍然存在,并将保持对象不被释放(或者至少在此调度块完成之前。
在上面的评论中,您会问:
我仍然不明白为什么
strongSelf
没有改变,因为自己nil
...
强引用永远不会被设置为nil
只是因为其他一些强引用(即使它是原始的强引用)被设置为nil
。 参考设置为nil
行为仅适用于weak
引用,而不适用于强引用。
当你的代码在第一个线程上执行sample = nil
时,所做的就是删除一个强引用。 它不会删除对象或类似的东西。 它只是删除了它的强大参考。 现在,调度块有自己的强引用,所有在sample = nil
时发生的事情是,具有两个强引用的对象现在只剩下一个强引用(调度块中的strongSelf
引用)。 只有在删除了最终的强引用时,才会释放对象并deinit
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.