NSNotificationCenter removeObserver:在dealloc和线程安全中

tee*_*pap 6 memory-management objective-c nsnotificationcenter automatic-ref-counting

我正在使用ARC,我正在[[NSNotificationCenter defaultCenter] removeObserver:someObserver];观察者的呼唤dealloc.

来自NSNotificationCenter类参考

确保在notificationObserver或addObserver中指定的任何对象之前调用此方法(或removeObserver:name:object :):selector:name:is is deallocated.

NSNotificationCenter不保留观察者.

Q1:NSNotificationCenter线程安全吗?

在这种情况下,观察者正被解除分配(并从观察中心移除观察者),另一个线程同时发布通知.

我遇到随机崩溃,我怀疑是这种情况.

Q2:这种情况可能吗?

Q3:它会导致EXC_BAD_ACCESS吗?

Q4:那么,[[NSNotificationCenter defaultCenter] removeObserver:someObserver];观察者的呼叫是否安全dealloc

Q5:如果不安全,我应该在哪里打电话removeObserver:

fel*_*ira 11

我自己偶然发现了这个问题:我在发送过程中有一个通知(总是发生在主线程中),而对象正在从后台线程中释放出来.我通过简单地removeObserver在主线程中执行并等待来修复它:

- (void)removeNotificationCenterObserver
{
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter removeObserver:self];
}

- (void)dealloc
{
    [self performSelectorOnMainThread:@selector(removeNotificationCenterObserver) withObject:self waitUntilDone:YES];
}
Run Code Online (Sandbox Code Playgroud)

这将一直等到当前运行循环周期结束,并在下一个运行循环周期开始时执行此消息.这可确保任何仍在运行的功能都将完成.


ksh*_*ksh 2

是的,NSNotificationCenter不保留观察者,但它的调度表中仍然有一个指向它的指针。

Q1:引用苹果文档

常规通知中心在发布通知的线程上发送通知。分布式通知中心在主线程上传递通知。有时,您可能需要在您确定的特定线程(而不是通知中心)上传递通知。例如,如果在后台线程中运行的对象正在侦听来自用户界面的通知(例如窗口关闭),您希望在后台线程而不是主线程中接收通知。在这些情况下,您必须捕获在默认线程上传递的通知并将其重定向到适当的线程。

Q2、3:是的。

Q4,5:据我所知,除非您陷入循环引用,否则它是安全的。我通常在UIViewControllers 的 / 和-viewWillAppear:其他类的/中添加/删除。-viewWillDisappear:-initdealloc