ARC 在解除分配之前是否将其引用类型实例属性设置为 nil?

Does ARC set its reference type instance properties to nil before deallocation?

我在阅读 this 时想到了这个问题。

我的问题参考下图:

一旦 john 设置为 nil,Person 实例将不再具有任何强引用,因此将被释放。但是 Apartment 有两个强引用,其中一个是 Person 实例上的 属性,很快就会被释放。我相信,这个强引用在解除分配后会继续保留,并且代码无法访问。

因此,将 unit14A 设置为 nil 将仅删除对 Apartment 实例的一个强引用,并且不应将其释放,因为由于上述原因还会有一个强引用案例.

但是,正如文档所述,Apartment 实例很快就被释放了。对我来说,这只有在 Person 实例释放时才会发生,它将其 公寓 属性 设置为 nil,通过删除那个强Apartment 实例参考。但是我找不到任何文档来验证这一点。

那么,Apartment 实例是如何被释放的?来自 Person 实例单元 属性 的强引用发生了什么?

谁能帮我理解一下?

您的直觉是正确的。当一个对象在 ARC 下被释放时,它持有的所有强引用首先被放弃——本质上它们被设置为 nil,但实际上实现可能不同。

这也是当方法 returns 或包含声明的代码块退出时发生的情况,局部变量中持有的所有强引用都被放弃。

所有详细信息都可以在 Clang documentation.

中找到

HTH

对象的生命周期取决于它的引用计数,而不是指向该对象的任何实际指针。

强引用是一种说法,强引用和弱引用没有区别,只是指针。不同之处在于,创建强引用时,指向的对象的引用计数会增加,而删除时,引用计数会减少。当对象的引用计数变为零时,对象将被释放。

Objective-C 对象是引用计数的,这意味着对于每个对象,系统会跟踪有多少其他对象持有对它的引用。这是对象的 引用计数 。两个特殊消息 retainrelease 用于在后台维护引用计数。一旦引用计数降为零,系统就会释​​放该对象。

ARC 提供 "magic" 以声明方式使引用计数工作。编译器知道你代码中的每一个强引用,所以当你这样做时

myStrongRef = nil;

编译器悄悄地在赋值前插入对release的调用:

[myStrongRef release];
myStrongRef = nil;

To me [deallocation of Apartment] can only happen if at the time of Person instance deallocation it sets its apartment property to nil, by that removing that strong reference on Apartment instance.

设置强引用nil 打破强引用的一种方式。这是足够的,但不是必需的。设置对 nil 的强引用的重要事情不是设置自身的行为,而是紧接在它之前发生的事情:强引用引用的实例收到一条 release 消息,指示它递减它的引用计数。这正是 ARC 在幕后为您所做的:它将 release 消息发送到 Apartment,而不设置 Personnil.

的引用

How does the Apartment instance get deallocated? What happened to the strong reference from the Person instance apartment property?

一旦来自 Person 的强引用将其 release 消息发送到 Apartment,该强引用就会消失。实际指针可能设置为 Apartment 的地址,但没有人关心它,因为 Person 本身是不可访问的。

显然不是解除分配之前,而是在解除分配期间。

当对象的引用计数变为零时,释放过程开始。该对象被标记为 "being deallocated"。到那时,对象 消亡(不像 Java,在那里它可以被恢复)。如果一个对象被标记为这样,它就不能分配给弱引用(它们保持为零)或强引用。

然后调用dealloc,也就是你写的dealloc方法。之后,强引用被设置为nil,减少它们的引用计数,然后关联对象被移除,最后对象的内存被删除。