Dealloc не вызывается в приложении ARC
У меня есть UIViewController, который выталкивается на контроллер контейнера, а затем выталкивается и, используя инструмент распределения, я вижу, что контроллер вида затем уничтожается. Однако точка останова в контроллере dealloc никогда не достигается. Кто-нибудь знает, почему dealloc не называется? Возможно ли, чтобы ARC уничтожил объект без вызова dealloc?
Кроме того, я отключил NSZombies (некоторые сказали, что это может привести к тому, что dealloc не будет срабатывать).
Edit:
Dealloc не делает много, просто печатает на консоли, и он никогда не вызывается:
- (void)dealloc
{
NSLog(@"Deallocating...");
}
Я не могу опубликовать контроллер контейнера - он проприетарный и слишком сложный. Dealloc называется последовательно на некоторых контроллерах, а не на других. Если я найду время, я попытаюсь опубликовать упрощенную версию, которая воспроизводит проблему.
Есть ли способ проверить, что NSZombies отключен?
Edit2
Я публикую скриншот из инструментов; мне кажется, что он правильно освобождается.
![enter image description here]()
Ответы
Ответ 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.
Так как этот не был отменен, мой основной класс также не был отменен. Перемещение этой переменной экземпляра в качестве свойства разрешило проблему для меня.
Вопрос: Я не уверен, почему это происходит. Имеет ли операционная система лучший контроль над свойствами класса, чем над переменными экземпляра? Кажется немного странным, что родительский класс, который содержит переменную экземпляра, не освобождается из-за своей переменной экземпляра.
Ответ 7
У вас есть NSZombieEnabled? См. Этот вопрос:
Почему объект не отменяется при использовании ARC + NSZombieEnabled
Я был в тупике от этого какое-то время...