Swift 5.0中的可选无主引用与弱引用

15

这在 Swift 5.0 中是被允许的:

class Person { 
    unowned var child: Person?
}

这得益于这个发行说明:

unownedunowned(unsafe) 变量现在支持可选类型。(47326769)

我很清楚地理解了 Swift 4.2 及之前版本中 weak 和 unowned 的区别。但是,我不确定为什么 Apple 决定将 unowned 变成了可选类型。即使在文档中(这些文档是 Swift 5.0 的文档),这个被实现的“提案”(我甚至可以在哪里找到添加可选 unowned 引用的动机?)没有更新,因为它说:

未拥有引用应始终具有值。因此,ARC 永远不会将未拥有引用的值设置为 nil,这意味着未拥有引用使用非可选类型进行定义。

上述内容已经不再正确。Apple 宣称唯一的功能差异是 unowned 引用期望具有与持有该引用的对象相同或更长的生命周期。我对技术使用方面很好奇。

当我使用 weak 引用和可选的 unowned 引用时会有什么区别?或者唯一的区别是仅在引用对象具有更长的生命周期时应使用可选的 unowned 引用?我期望有更多的区别...

1个回答

18

你误解了发布说明以及该语言变更的含义。

为什么苹果决定使未拥有的可选类型

他们没有这样做。你可以,而且通常会,仍然说

unowned let owner : MyViewController

这里唯一的变化是,之前不允许未拥有(unowned)的变量为 Optional 类型,而现在允许了。这个调整解决了一个烦人的边缘情况,仅此而已。

上面的话已经不再正确

不,它依然正确。与以前完全没有改变:

  • 弱引用必须声明为 Optional 类型;它们不会保留对象引用,但会跟踪所引用的对象,如果该对象不存在,则会回退到 nil
  • 未拥有的引用不保留所引用的对象,也不跟踪所引用的对象,因此需要你防止该对象消失,否则可能会出现悬空指针和崩溃。

唯一改变的是原来还有一个规则,即未拥有的引用类型不能是 Optional。现在这个规则已经被取消了。

正如您所指出的那样,如果未拥有的引用类型是 Optional,那么这必须是一个 var 引用,而不是 let 引用(因为如果你没有将其从 nil 改为实际值或相反,就将其设置为 Optional 是没有意义的)。

一个典型的用例非常像您提供的内容:

class Node {
    unowned var parent: Node?
}

我们可以合理地说,这个节点可能有父节点,也可能没有(因为它可能在图的顶部),但是如果它有父节点,那么该父节点应该未拥有(父节点应保留其子节点,但子节点不应保留其父节点)。以前,表达这一点的唯一方法是使用弱引用,这会带来一些不必要的开销,并且是多余的,因为我们绝对可以保证,如果一个节点有父节点,则父节点将比子节点存在更长的时间。现在,您可以清楚地表达自己的意思,这通常是一件好事。


因此,例如我在 http://www.apeth.com/swiftBook/ch05.html#_weak_references 和 http://www.apeth.com/swiftBook/ch05.html#_unowned_references 中的所有解释仍然是正确的,只需删除“实际上,它[一个无主引用]不能是可选项”这句话即可。 - matt
我必须将可选的unowned引用标记为'var',而不能使用'let',这是否有任何原因?当尝试这样做时,会出现以下错误:''unowned' must be a mutable variable, because it may change at runtime'。我不确定为什么会这样,因为通常非可选的unowned let也可以是nil(这有点指示了编程错误,但是除此之外)。 - J. Doe
因为通常情况下,非可选的未拥有的常量(unowned let)可能为空(nil)。这些是非常奇怪的词汇。你能再解释一下吗?在Swift中,唯一可能是nil的是可选类型(Optional),也就是nil是可选类型的一个可能值。那么如何将“非可选”和“nil”放在同一个句子中呢? - matt
如果我表达不清楚,我可以在另一个问题中发布一些代码片段。 - J. Doe
3
@AhmadF 对于你也许会完全按预期工作,但正如我在答案中所说,它会带来一些可能不必要的开销,因为你要让运行时跟踪弱引用以防被释放。如果我们知道父对象在子对象生命周期内永远不会被释放,那么这是浪费时间、空间和计算复杂性。因此,就像我在答案中所说的那样,无主可选项让你表达意思并消除所有这些复杂性。 - matt
显示剩余4条评论

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