为什么要在依赖 self 的块中指定 [unowned self]?

Why specify [unowned self] in blocks where you depend on self being there?

我希望 self 不为 nil,我相信在块执行期间它会是。那么为什么要明确指定 [unowned self] 呢?

object.executeBlock {
    date = self.lastModified
}

object.executeBlock { [unowned self] in
    date = self.lastModified
}

编辑: 好吧,我的票数越来越低,所以让我们再试一次。问:假设我有问题。那个问题是我想阻止引用循环。我有两个选择。我可以使用 [unowned self] 或者我可以使用 [weak self]。因此,我的问题是:从这两个选项中,我为什么要选择 [unowned self] ?为什么不每次都选择【弱小的自己】?

唯一真正想要使用 [unowned self][weak self] 的时候是创建强引用循环的时候。强引用循环是指存在一个所有权循环,对象最终拥有彼此(可能通过第三方),因此它们永远不会被释放,因为它们都确保彼此坚持。

你那里有很强的引用循环吗?

"The Language Guide claims you should use unowned if the closure and containing object reference each other and will be destroyed at the same time. Presumably that's to avoid the cost of safely nil'ing out a weak reference in an object that's about to dealloc anyway."

http://www.russbishop.net/swift-capture-lists

所以 [unowned self] 使 self 成为一个隐式解包的可选项,为了方便不自己解包,当然如果它实际上是 nil 则有崩溃的风险。

为什么是 [unowned self]? self指向object,object有executeBlock,executeBlock又指向self,形成内存循环。

但是当你说 [unowned self] 时:系统不会将 self 保存在内存中以使闭包工作。它将假定在执行闭包时 self 始终存在。 如果不是出于某种原因,不会有未定义的行为或类似的事情,但您的应用程序会崩溃,因为它是运行时错误。

斯坦福 iOS 开发老师 Paul Hegarty 是这样解释的。

我在别处回答过这个问题。这是悬崖笔记:

如果在闭包中 self 可以为 nil 使用 [weak self]。

如果 self 在闭包中永远不会为 nil,请使用 [unowned self]。

如果当你使用 [unowned self] 时它崩溃了,我猜想 self 在那个闭包的某个时刻是 nil,这就是为什么你不得不使用 [weak self] 的原因。

我真的很喜欢手册中关于在闭包中使用 strong、weak 和 unowned 的整个部分:

https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html

在闭包中使用 self 时可能 nil 的情况下,您不得不使用 weak 语义(否则有崩溃的风险)。

在您可以推断出 self 永远不会是 nil 的情况下,您可以选择指定其中之一:"choose",因为两者都是正确的并且会起作用。可以说,可以认为一个比另一个 "more correct",因为两种语义都满足要求,但一个更具体。

您可能希望指定 unowned 而不是 self 的两个原因:

  • 方便
  • 文档

unowned 引用会更方便使用,因为它不需要解包。它也可能更有效,因为编译器可能不必为安全释放生成尽可能多的清理代码。

就文档而言,您正在对您的程序认为是真实的事情做出某种断言。如果违反了该假设(假设它是有效的),您可能希望以崩溃的形式了解它。

随后,这也可能使变量的使用不那么费力:您考虑一下并记录您的推理,即它必须始终预先存在,然后每次使用它时,您都不必进一步花费精神能量想知道 "what do I do if this isn't here?"。

可以说,使用 let 绑定或 guard 语句也可以实现后者。