繁体   English   中英

将引用转换回封闭内部的强引用,内存管理,swift

[英]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对象时(通过超出范围或通过显式设置samplenil ),这个strongSelf强引用仍然存在,并将保持对象不被释放(或者至少在此调度块完成之前。

在上面的评论中,您会问:

我仍然不明白为什么strongSelf没有改变,因为自己nil ...

强引用永远不会被设置为nil只是因为其他一些强引用(即使它是原始的强引用)被设置为nil 参考设置为nil行为仅适用于weak引用,而不适用于强引用。

当你的代码在第一个线程上执行sample = nil时,所做的就是删除一个强引用。 它不会删除对象或类似的东西。 它只是删除了它的强大参考。 现在,调度块有自己的强引用,所有在sample = nil时发生的事情是,具有两个强引用的对象现在只剩下一个强引用(调度块中的strongSelf引用)。 只有在删除了最终的强引用时,才会释放对象并deinit

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM