Dealloc не вызывается в приложении ARC - PullRequest
37 голосов
/ 10 февраля 2012

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

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

Edit:

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

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

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

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

Edit2

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

enter image description here

Ответы [ 7 ]

92 голосов
/ 21 сентября 2012

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

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

__unsafe_unretained TableViewController *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
        if (weakSelf.tableView) {
            [weakSelf.tableView reloadData];
        }
    }];
23 голосов
/ 14 сентября 2013

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

20 голосов
/ 26 августа 2012

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

Что нужно проверить:

  1. Есть ли у вас объект, который ссылается на VC?
  2. Если вам нужно сослаться на VC, убедитесь, что вы использовали атрибут «__unsafe_unretained» или «слабый» (iOS5 +), чтобы не было цикла сохранения.

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

16 голосов
/ 30 сентября 2012

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

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

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

15 голосов
/ 17 декабря 2014

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

Проверьте своих делегатов!Для свойства делегата должно быть указано weak:

weak var delegate: SomeProtocol?

или

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

10 голосов
/ 11 июня 2013

Вот еще один совет (случилось со мной):

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

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

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

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

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

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

5 голосов
/ 26 августа 2012

У вас есть NSZombieEnabled?См. Этот вопрос:

Почему объект не освобождается при использовании ARC + NSZombieEnabled

Я на некоторое время был озадачен этим ...

...