Objective-C保留2个对象之间的循环

时间:2018-03-31 03:53:07

标签: objective-c retain-cycle strong-reference-cycle

以下是代码:

TestA *ta = [[TestA alloc] init];
TestB *tb = [[TestB alloc] init];  

ta.b = tb;
tb.a = ta;

我尝试设置ta = niltb = nil。它没有用,但ta.b = nil有效。为什么呢?

1 个答案:

答案 0 :(得分:3)

  

我尝试设置ta = niltb = nil,但它没有用,

这是因为,正如您所指出的,您有一个强大的参考周期" (以前称为"保留周期")。这是强参考周期的定义。

TestA引用的ta对象仍然引用TestB最初引用的tb对象。同样,TestB引用的tb对象仍然保留对TestA最初引用的ta实例的强引用。因此,即使将tatb指针都设置为nil,它们最初指向的实际对象仍然保持对彼此的引用。因此循环。

关键的一点是,当您将tatb指针设置为nil时,除了删除对这些TestA和{{{{}}的引用之外,它不会执行任何操作1}}实例。但只要有其他东西保持对这些实例的强烈引用(在这种情况下,他们“保持对彼此的强引用),他们就不会被解除分配。我们将与这两个对象相关联的内存称为“被抛弃”,即,即使它们未被释放,您也没有任何对它们的引用,因为它们在相互较强的引用周期中被捆绑在一起。

"调试内存图"功能enter image description here,在可视化中非常有用。因此,在我将TestBta设置为tb之后,我查看了内存图,它显示我的nil不再引用这两个对象,但是他们仍然互相引用:

enter image description here

  

ViewController有效。为什么?? !!

这可行(假设您在将ta.b = nil设置为ta之前执行此操作),因为它会破坏强引用周期。当您将nil设置为ta.b时,nil对象不再具有任何强引用,并且可以将其取消分配。并且,一旦该TestB实例被释放,它将删除对该TestB实例的引用,以便TestA实例也将被释放,因为它的最后一个强引用将被删除

也许不用说,但是你防止这个问题的方法是制作一个属性TestA。例如,如果weak是逻辑“父”对象,则您可能会在TestA b属性中生成TestA属性,但请生成strong } a TestB属性中的属性。这解决了强大的参考周期并完全消除了这个问题。