我有一个NSOperation子类,它使用核心数据。
它有一个自定义的init方法,如下所示:
- (id)initWithManagedObjectContext:(NSManagedObjectContext*)moc;
正如您所知,核心数据托管对象上下文不是线程安全的,每个线程都需要自己的托管对象上下文。在创建这个NSOperation时,我创建了一个新的NSManagedObjectContext,并将其作为moc
参数传递给初始值设定项。
这里是重要的部分:初始化时,我注册一个通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc];
在-dealloc
中,我从NotificationCenter注销:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:nil];
}
在我迁移到ARC之前,这段代码运行得非常好。
现在在ARC下,我得到了这样的堆栈跟踪:
1) NSOperation对象接收-delloc
2) 在NSNotificationCenter上调用-removeObserver:name:object:。
3) __arclite_objc_release
4) NSOperation对象接收-delloc
5) 在NSNotificationCenter上调用-removeObserver:name:object:。
6) __arclite_objc_release
7) NSOperation对象接收-delloc
8) 在NSNotificationCenter上调用-removeObserver:name:object:。
9) __arclite_objc_release
这种情况将永远持续下去-dealloc,从通知中心注销,__arclite_objc_release,-delloc。。。
即使NSOperation对象已被销毁,__arclite_objc_release似乎也会触发对-dealloc的调用!
这怎么可能?
更新:由于一些疯狂奇怪的原因,在我将通知中心注销代码更改为以下代码后,到-delloc的无限循环消失了:
[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:self.managedObjectContext];
因此,我没有简单地注销任何发件人发送的任何通知,而是明确地注销了特定发送器发送的任何通知书。
显而易见的问题是:由于ARC将代码插入-delloc,我不知道它是在我的-delloc代码之前插入,还是在我的/delloc代码之后插入。
阅读您的更新,您似乎应该在不同的地方调用[super dealloc]
(如果您在)。尝试在dealloc方法中首先调用它,然后注销NSNotification