У меня есть подкласс 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 кода .