Swift中的强引用,弱引用和无主引用

Swift依靠自动引用计数(ARC)通过在对象的强引用为零时释放对象的内存来管理对象的生命周期。 但是,当两个对象彼此保持强引用时,可能会发生强引用循环。

强烈 参考

强大的参考保护 ARC释放对象后,其保留计数增加1。

默认情况下,对类实例的引用是强的。 基本上,只要任何东西都强烈引用对象,就不会释放该对象。 如下面的示例所示,当流程是从父级到子级时,可以使用强引用。

当我们将对象设置为nil时,会同时调用instrument和player deinit方法。

强参考循环–内存泄漏
现在,我们将一个玩家数组添加到Instrument实例(第3行),并在初始化一个Player实例(第5行)时,将其添加到该乐器的玩家数组(第22行)。

当我们将实例设置为nil时,不会调用instrument和player的deinit方法。

当我们将乐器实例设置为nil时,ARC会检查是否有一个实例保留对其的强引用,并且由于存在一个播放器实例对其具有强引用,因此不会释放该对象( 强引用周期 ),这导致我们陷入所谓的内存泄漏

弱引用

弱引用不能防止对象被ARC释放(它不会将其保留计数增加1),并且始终是可选的

弱引用只是指向对象的指针,该指针不能保护对象免遭ARC释放。 当不再有对它的强引用时,该引用将被更改为nil。

我们可以使用弱引用以避免强引用周期和内存泄漏(第17行):

当Instrument设置为nil时,唯一引用该实例的实例是播放器实例,并且由于它是弱引用,因此ARC会释放Instrument实例。

多余的参考

无主引用类似于弱引用(ARC不会将其保留计数增加1),但是具有额外的好处,这是非可选的。

无主引用是非归零的。 这意味着当对象被释放时,它不会使指针归零。 正如我们在下面的示例中看到的那样,将弱引用(第17行)更改为无主​​引用,其结果与以前相同。

根据Apple的文档:

仅当确定引用始终引用尚未取消分配的实例时,才使用无主引用。

如果在释放该实例后尝试访问一个未拥有的引用的值,则会收到运行时错误。