闭包的强引用循环?

9

当Swift Closure引用self时会产生强引用循环,就像这个例子:

class Test {
  var name = "Hello"

  func doSomething() {
    {() -> Void in 
      self.name = "otherName"
    }()
  }

}

在之前的例子中,我创建了一个强引用循环,因此需要使用以下方法进行修复:
class Test {
  var name = "Hello"

  func doSomething() {
    {[unowned self] () -> Void in 
      self.name = "otherName"
    }()
  }

} 

问题: 如果我在闭包中使用self,我必须始终使用 unowned self 还是有一些情况需要使用 weak self


2
闭包是非逃逸的(意思是闭包不是异步的或者没有延迟,因此它可以“保持在范围内”)。您不需要使用它们中的任何一个。请参见逃逸与非逃逸。关于何时需要使用其中之一的示例,请参见这里 - mfaani
1个回答

17
如果我在闭包中引用自己,我是否必须始终使用unowned self,还是有时候必须使用weak self?
实际上,都不需要。大多数情况下,只需正常地引用self并且不进行任何内存管理即可。只有在存在保留循环的危险时,才需要担心内存管理。除非将闭包存储在某个位置(例如self的属性)中,否则不存在此类危险。
您可以通过添加deinit实现轻松证明这一点:
class Test {
    var name = "Hello"

    func doSomething() {
        {() -> Void in
            self.name = "otherName"
            }()
    }
    deinit {
        println("bye")
    }
}

现在创建一个测试实例并立即释放它:
func testTest () {
    let t = Test()
}

你在控制台中看到了“bye”,证明实例已经被正确释放。在这段代码中从未出现任何类型的“强引用循环”。你的担忧是没有根据的。
顺便说一下,你使用“闭包”这个词是错误的。每个Swift函数都是一个闭包。如果仅仅因为在闭包中使用了“self”关键字就存在保留周期问题,那么每个Swift函数都将面临这个问题-显然这不是事实。在匿名函数中,weakunowned self发挥作用的地方是-只有当该匿名函数本身也被self保留时,才会出现此问题。

对于可能出现保留循环的情况,以及weakunowned之间的区别,请参阅我的书:http://www.apeth.com/swiftBook/ch05.html#_memory_management - matt
请问您能否举个例子,说明何时使用它以及何时不使用它? - user4788711
请看我刚才给您发的链接! - matt
1
特别是这个部分:http://www.apeth.com/swiftBook/ch05.html#SECweakSelf - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接