【问题标题】:Strong Reference Cycles for Closures?闭包的强大参考周期?
【发布时间】:2015-05-03 16:40:20
【问题描述】:

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

【问题讨论】:

  • 闭包是非转义的(意味着闭包不是异步的或没有延迟,因此它可以“留在范围内”)。你不需要使用它们中的任何一个。见escaping vs non-escaping。有关您需要在哪里使用的示例,请参阅here

标签: swift memory-management closures


【解决方案1】:

如果我在闭包中引用 self,我是否必须使用始终无主的 self,或者在某些情况下我必须使用弱 self?

两者都没有。在大多数情况下,只需正常引用self,对其内存管理不做任何事情。如果存在保留循环的危险,您只需要担心内存管理,除非您将闭包存储在某个地方,例如 self 的属性,否则不会有这种危险。

您可以通过添加 deinit 实现轻松证明这一点:

class Test {
    var name = "Hello"

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

现在创建一个测试实例并立即释放它:

func testTest () {
    let t = Test()
}

您在控制台中看到“再见”,证明实例已按良好顺序释放。这段代码中从来没有任何类型的“强引用循环”。您的担心毫无根据。

[顺便说一句,您使用“关闭”一词是错误的。 每个 Swift 函数都是一个闭包。如果仅仅因为在闭包中使用了self 这个词而存在保留周期问题,那么每个 Swift 函数都会受到这个问题的影响——显然情况并非如此。 weakunowned self 发挥作用的地方是在一个 anonymous 函数中——而且,正如我之前所说,如果该匿名函数本身也被 self 保留。]

【讨论】:

猜你喜欢
  • 2020-03-08
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
  • 2017-06-10
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多