Подтвердить что ты не робот

Dealloc не вызывается в приложении ARC

У меня есть UIViewController, который выталкивается на контроллер контейнера, а затем выталкивается и, используя инструмент распределения, я вижу, что контроллер вида затем уничтожается. Однако точка останова в контроллере dealloc никогда не достигается. Кто-нибудь знает, почему dealloc не называется? Возможно ли, чтобы ARC уничтожил объект без вызова dealloc?

Кроме того, я отключил NSZombies (некоторые сказали, что это может привести к тому, что dealloc не будет срабатывать).

Edit:

Dealloc не делает много, просто печатает на консоли, и он никогда не вызывается:

- (void)dealloc { NSLog(@"Deallocating..."); }

Я не могу опубликовать контроллер контейнера - он проприетарный и слишком сложный. Dealloc называется последовательно на некоторых контроллерах, а не на других. Если я найду время, я попытаюсь опубликовать упрощенную версию, которая воспроизводит проблему.

Есть ли способ проверить, что NSZombies отключен?

Edit2

Я публикую скриншот из инструментов; мне кажется, что он правильно освобождается.

enter image description here

4b9b3361

Ответ 1

Я столкнулся с подобной проблемой. Есть ли у вас блоки, в которых вы имеете дело с "я"? У меня было несколько блоков для наблюдения за уведомлениями в моем init, где я имел в виду "я". В ARC self сохраняется в блоках. Мой деаллок не вызывался, и именно там я снимал наблюдение.

Трюк заключается в создании ссылки __weak (iOS 5+) или __unsafe_unretained (iOS 4.x) на ваше "я" и использование этого для доступа к себе или к любым _iVars (они также будут удерживать "я" ) в блоке. Вот пример.

__unsafe_unretained TableViewController *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
        if (weakSelf.tableView) {
            [weakSelf.tableView reloadData];
        }
    }];

Ответ 2

В моем случае это было NSTimer. Он сохраняет свою цель, поэтому вам нужно сделать недействительным таймер, когда вы закончите с контроллером представления.

Ответ 3

Если dealloc не вызывается VC, я бы поспорил, что в вашем коде есть круговая ссылка, которая предотвращает вызов ARC из dealloc.

Некоторые вещи для проверки:

  • У вас есть экземпляр объекта, ссылающийся на VC?
  • Если вам нужно ссылаться на VC, убедитесь, что вы использовали атрибут __unsafe_unretained или "слабый" (iOS5 +), чтобы цикл сохранения не выполнялся.

Я был укорочен в прикладе, когда мои объявления делегатов не использовали __unsafe_unretained.

Ответ 4

Даже с ARC вы можете вручную проверить счетчик ссылок:

CFIndex rc = CFGetRetainCount((__bridge CFTypeRef)myObj);

Вы можете точно знать, находится ли ваш код в цикле памяти.

Ответ 5

Моя проблема была делегатами.

Проверьте своих делегатов! Свойство делегата должно иметь weak:

@property (weak, nonatomic) id<SomeProtocol> delegate;

Ответ 6

Вот еще один отзыв (со мной):

tl; dr: Посмотрите также на переменные экземпляра класса, а не только на свойства класса. Вы выделяете какую-либо переменную экземпляра в коде и не устанавливаете ее на nil позже?

У меня был класс с множеством свойств (@property (nonatomic, strong) и @property (nonatomic, weak)) в его заголовочном файле. Я прокомментировал эти свойства один за другим, чтобы увидеть, изменит ли это что-либо. Это не так. Основной класс все еще не был освобожден. Поэтому проблема не в свойствах.

То, что я сделал потом, это посмотреть на переменные экземпляра. У меня была одна переменная экземпляра (которая была UIViewController), которую я создал на viewDidLoad. Это никогда не получило dealloc-ed!

Когда я удаляю эту переменную, достаточно уверен, мой основной класс называется dealloc.

Так как этот не был отменен, мой основной класс также не был отменен. Перемещение этой переменной экземпляра в качестве свойства разрешило проблему для меня.

Вопрос: Я не уверен, почему это происходит. Имеет ли операционная система лучший контроль над свойствами класса, чем над переменными экземпляра? Кажется немного странным, что родительский класс, который содержит переменную экземпляра, не освобождается из-за своей переменной экземпляра.