为啥在你依赖自我存在的区块中指定 [unowned self]?

Posted

技术标签:

【中文标题】为啥在你依赖自我存在的区块中指定 [unowned self]?【英文标题】:Why specify [unowned self] in blocks where you depend on self being there?为什么在你依赖自我存在的区块中指定 [unowned self]? 【发布时间】:2015-10-04 17:28:35 【问题描述】:

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

object.executeBlock 
    date = self.lastModified

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

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

【问题讨论】:

【参考方案1】:

“语言指南声称如果闭包和包含对象相互引用并且将同时被销毁,则应该使用 unowned。大概这是为了避免安全地消除对象中的弱引用的成本无论如何都要解除分配。”

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

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

【讨论】:

【参考方案2】:

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

你那里有很强的参考周期吗?

【讨论】:

您好,Arsen,感谢您的回复。恐怕这并不能完全回答我的问题。可以在此处找到类似的问题,并且该问题的答案也无法回答“为什么使用无主的自我”的真正问题。恐怕我只想知道我需要使用“无主的自我”而不是“弱自我”。这里的答案表明,如果我们使用弱,那么 self 是一个可选的。我可以接受......但你为什么要使用无主的自我?特别是(只是)无主的自我。 ***.com/questions/24320347/… @robdashnash:你的问题不是关于 unownedweak 的问题。它询问unowned 与什么都没有,这个答案回答了你的问题。至于为什么unowned而不是weak,答案是你也可以使用weak self,但是self是可选的,你必须以某种方式打开它,而如果你知道self仍然会活着,unowned self 更方便,因为self 是一个非可选类型,这样你就可以在不显式解包的情况下使用它。【参考方案3】:

我在其他地方回答了这个问题。这是悬崖笔记:

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

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

如果当你使用 [unowned self] 时它崩溃了,我猜想 self 在那个闭包中的某个时刻是 nil,这就是为什么你必须使用 [weak self] 来代替。

我真的很喜欢手册中关于在闭包中使用强、弱和无主的整个部分:

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

【讨论】:

【参考方案4】:

为什么是[无主的自我]? self指向object,object有executeBlock,executeBlock又指向self,形成内存循环。

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

这是由斯坦福 iOS 开发教师 Paul Hegarty 解释的。

【讨论】:

我很惊讶有多少人误读了这个问题。我不是在问我为什么要避免保留循环,因为我知道为什么这很重要。我也同意,Paul Hegarty 是人类中的神。我要问的是,当我也有“弱”的时候,为什么我要特别选择无主的自我。无论如何,我已经回答了我自己的问题。在这个线程中查看我的答案,以““语言指南声称...”开始【参考方案5】:

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

如果您可以推断出self 永远不会是nil,您可以选择指定:“选择”,因为两者都是正确的并且可以工作。可以说,一种可以被认为比另一种“更正确”,因为两种语义都满足要求,但一种更具体。

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

方便 文档

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

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

随后,这也可能使变量的使用不那么费力:您考虑它并记录您认为它必须始终存在于前面的推理,然后每次使用它时,您都不必花费更多的精力想知道“如果这不在这里,我该怎么办?”。

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

【讨论】:

以上是关于为啥在你依赖自我存在的区块中指定 [unowned self]?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 UIViewPropertyAnimator 中使用“unowned”

为啥我们需要在 bindParam() 中指定参数类型?

为啥在列名中指定主/外键属性

为啥我们在 android xml 文件中指定命名空间?

为啥 Firefox 2 显示的字体大于 CSS 中指定的字体?

为啥我需要在 Swift 的类中指定变量的类型?