我了解Swift中weak
和unowned
之间的用法和表面区别:
我所见过的最简单的示例是,如果存在Dog
和Bone
,那么Bone
可能对Dog
的引用较弱(反之亦然),因为它们可以彼此独立存在。
另一方面,在Human
和Heart
的情况下,Heart
可能具有对人的unowned
引用,因为一旦Human
被...“取消引用”,就无法再合理地访问Heart
。那和Customer
和CreditCard
的经典示例。
因此,这不是重复询问的问题。
我的问题是,拥有两个类似的概念有什么意义?有哪些内部差异需要两个关键字来代表本质上99%的同一事物?问题是为什么存在差异,而不是差异是什么。
假设我们可以像这样设置一个变量:weak var customer: Customer!
,unowned
变量为非可选的优点是有争议的。
...也许出于这个原因,编译器可以进行更有效的优化。
是真的,还是在幕后发生了其他事情,提供了一个令人信服的论据来保留两个关键字(尽管基于Stack Overflow流量的微小区别显然使新手和有经验的开发人员都感到困惑)。
我最感兴趣的是从Swift编译器(或其他编译器)工作的人那里听到的消息。
最佳答案
它们根本不相似。它们是一样的。
weak
是一个非常复杂的概念,是在引入ARC时引入的。它执行了近乎奇迹般的任务,即允许您避免保留循环(通过避免使用强引用),而不必担心当引用的对象不存在时悬挂指针会导致崩溃—这在ARC之前一直存在被介绍了。 unowned
是非ARC弱的(具体来说,它与non-ARC assign
相同)。在引入ARC之前,这是我们曾经不得不冒险的原因,它是导致如此多崩溃的原因。这是非常危险的,因为如果所引用的对象不存在,则可能会悬空指针并导致崩溃。 产生这种差异的原因是,为了执行其奇迹,
weak
涉及到运行时的许多额外开销,这些开销由编译器插入到幕后。 weak
引用是由您进行内存管理的。特别是,运行时必须维护以这种方式标记的所有引用的暂存器,并对其进行跟踪,以便如果弱引用的对象不存在,则运行时可以找到该引用并将其替换为nil
以防止指针悬空。因此,在Swift中,
weak
引用始终是对Optional的引用(正是这样,因此可以将其替换为nil
)。这是额外的开销来源,因为使用Optional会带来额外的工作,因为必须始终将其拆开才能完成任何工作。因此,在适用的地方,
unowned
始终是首选。但是除非绝对安全,否则请不要使用它!使用unowned
,您将放弃自动内存管理和安全性。您有意恢复到ARC之前的糟糕日子。在我的用法中,常见的情况是在闭包需要包含
self
的捕获列表以避免保留周期的情况下出现的。在这种情况下,几乎总是可以在捕获列表中说出[unowned self]
。当我们这样做时:[weak self]
是需要使用它才能进行包装的Optional。