Почему отмена регистрации получателя уведомлений в -dealloc создает бесконечный цикл в ARC? - PullRequest
1 голос
/ 23 января 2012

У меня есть подкласс NSOperation, который использует Core Data.

У него есть собственный метод init, подобный этому:

- (id)initWithManagedObjectContext:(NSManagedObjectContext*)moc;

Как вы, возможно, знаете, контексты управляемого объекта Core Data не являются поточно-ориентированными, и каждому потоку необходим собственный контекст управляемого объекта. При создании этой операции NSO я создаю новый NSManagedObjectContext и передаю его в качестве аргумента moc инициализатору.

Вот важная часть: При инициализации я регистрируюсь для уведомления:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextDidSave:)  name:NSManagedObjectContextDidSaveNotification object:moc];

В -dealloc Я отменяю регистрацию в Центре уведомлений:

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:nil];
}

До перехода на ARC этот код прекрасно работал.


Теперь в ARC я получаю трассировку стека, например:

1) Объект NSOperation получает -dealloc

2) -removeObserver: имя: объект: вызывается в NSNotificationCenter.

3) __arclite_objc_release


4) Объект NSOperation получает -dealloc

5) -removeObserver: имя: объект: вызывается в NSNotificationCenter.

6) __arclite_objc_release


7) Объект NSOperation получает -dealloc

8) -removeObserver: имя: объект: вызывается в NSNotificationCenter.

9) __arclite_objc_release


Это продолжается вечно. -dealloc, отменить регистрацию в центре уведомлений, __arclite_objc_release, -dealloc, ...

Похоже, что __arclite_objc_release запускает вызов -dealloc, даже если объект NSOperation был уничтожен!

Как это возможно?

Обновление: По какой-то безумно странной причине бесконечный цикл для -dealloc исчез после того, как я изменил код отмены регистрации моего центра уведомлений на этот:

[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:self.managedObjectContext];

Таким образом, вместо простой отмены регистрации для любого уведомления, отправленного любым отправителем, я явно отменяю регистрацию для любого уведомления, отправленного конкретным отправителем.

Очевидная проблема заключается в следующем: поскольку ARC вставляет код в -dealloc, я не знаю, будет ли он вставлен до my -dealloc кода или после my -dealloc кода .

1 Ответ

0 голосов
/ 23 января 2012

Читая ваше обновление, кажется, вы должны позвонить [super dealloc] в другом месте, чем где вы находитесь (если вы есть).Попробуйте сначала вызвать его в методе dealloc, затем отмените регистрацию вашего NSNotification

...