为什么在-dealloc中注销通知接收器会在ARC下创建一个无限循环



我有一个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