Objective-C сохранить цикл между 2 объектами
Вот код:
TestA *ta = [[TestA alloc] init];
TestB *tb = [[TestB alloc] init];
ta.b = tb;
tb.a = ta;
Я пытался установить ta = nil
или же tb = nil
, Не сработало но ta.b = nil
работал. Зачем?
1 ответ
Я пытался установить
ta = nil
или жеtb = nil
это не сработало,
Это потому, что, как вы указали, у вас есть "сильный референтный цикл" (ранее известный как "удерживающий цикл"). Это само определение сильного референтного цикла.
TestA
возражать, что ta
ссылка все еще имеет ссылку на TestB
возражать, что tb
изначально ссылка. Аналогично TestB
возражать, что tb
ссылка по-прежнему держит сильную ссылку на это TestA
пример того, что ta
изначально ссылка. Так что даже после того, как вы установите оба ta
а также tb
указатели на nil
фактические объекты, на которые они первоначально указывали, все еще сохраняют ссылки друг на друга. Отсюда и цикл.
Ключевое наблюдение заключается в том, что когда вы устанавливаете ta
а также tb
указатели на nil
ничего не делает, кроме удаления ваших ссылок на эти TestA
а также TestB
экземпляров. Но пока что-то еще поддерживает строгую ссылку на эти экземпляры (в этом случае они поддерживают строгие ссылки друг на друга), они не будут освобождены. Мы называем память, связанную с этими двумя объектами, "заброшенной", т. Е. У вас нет ссылок на них, даже если они не освобождены, потому что они связаны друг с другом циклом сильных ссылок.
Функция "График отладочной памяти", действительно полезно для визуализации этого. Итак, после того, как я установил ta
а также tb
чтобы быть nil
Я посмотрел на график памяти, и он показывает, что мой ViewController
больше не было ссылки на эти два объекта, но они все еще ссылаются друг на друга:
но
ta.b = nil
работал. Зачем??!!
Это работает (при условии, что вы сделали это до установки ta
в nil
), потому что это нарушает цикл сильных ссылок. Когда вы установите ta.b
в nil
, TestB
У объекта больше нет сильных ссылок, и он может быть освобожден. И, как только это TestB
экземпляр освобожден, он удалит ссылку на него TestA
например, так что TestA
экземпляр также будет освобожден, так как последняя сильная ссылка на него будет удалена.
Возможно, излишне говорить, но способ предотвратить эту проблему состоит в том, чтобы сделать одно из свойств weak
, Например, если TestA
является логическим "родительским" объектом, вы, вероятно, сделаете b
недвижимость в TestA
strong
собственности, но сделать a
недвижимость в TestB
weak
имущество. Это разрешает сильный референсный цикл и полностью устраняет эту проблему.