我使用ARC和我打电话[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
在观察者dealloc
。
从NSNotificationCenter类参考
一定要调用这个方法(或removeObserver:名称:对象:) notificationObserver之前或在指定的addObserver任何对象:选择:名称:对象:被释放。
NSNotificationCenter不保留观察员。
Q1:是NSNotificationCenter
线程安全的?
在情况下,观察者被释放(并从通知中心去除观察者)和另一个线程在同一时间后的通知。
我遇到随机崩溃,我怀疑是这种情况。
问题2:这种情况可能吗?
Q3:是否导致EXC_BAD_ACCESS
?
Q4:那么,是不是安全地调用[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
在观察者的dealloc
?
Q5:如果它是不是安全,我应该在哪里打电话removeObserver:
我只是偶然到这个问题我自己:我有一个通知只是处于发送(这总是发生在主线程),而对象是在从后台线程正在释放过程中的过程。 我固定它通过简单地执行removeObserver
在主线程和等待:
- (void)removeNotificationCenterObserver
{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter removeObserver:self];
}
- (void)dealloc
{
[self performSelectorOnMainThread:@selector(removeNotificationCenterObserver) withObject:self waitUntilDone:YES];
}
这也是在等待,直到当前运行的循环周期结束,并在下次运行循环周期的开始执行此消息。 这确保了仍在运行的所有功能将结束。
是的, NSNotificationCenter
不保留观察员,但它仍然有一个指向它在它的调度表。
Q1:引用苹果文档
定期通知中心中通知已经张贴在线程上传递通知。 分布式通知中心主线程上传递通知。 有时,你可能需要将通知在由你,而不是确定的通知中心的特定线程交付。 例如,如果在后台线程中运行的对象正在监听从用户接口通知,诸如窗口关闭,你想接收在后台线程,而不是主线程的通知。 在这种情况下,你必须捕捉的通知,因为它们在默认线程交付并重定向到适当的线程。
Q2,3:是的。
Q4,5:据我所知,除非你再次陷入循环引用是安全的。 我通常添加/删除中-viewWillAppear:
/ -viewWillDisappear:
为UIViewControllers和-init
/ dealloc
其他类。
我想知道同样的事情,我找不到它记录。 这是我认为正在发生的事情。
removeObserver:
是不是线程,你希望它是一路安全。
想想下面的情况。 最后参考观察者被释放,而在线程A线程A执行代码调用观察者dealloc
方法。 同时,观察到的对象执行[NSNotificcationCenter postNotificationName:object:]
从螺纹B.这导致不可避免的竞争条件。 也就是说,通知将在飞行 ,而你的目标是其内dealloc
方法。
- (void)init {
...
[[NSNotificcationCenter defaultCenter] addObserver:self
selector:@selector(callback:)
name:@"whatever"
object:nil];
...
}
- (void)dealloc {
// If the observed object posts the notification on thread B while
// thread A is here, there's a race! At best, thread B will be
// in callback: while thread A is here in dealloc. That's probably
// not what you expect. The worst case is that thread B won't make
// make it to callback: until after thread A completes the dealloc
// and the memory has been freed. Likely crash!
[[NSNotificationCenter defaultCenter] removeObserver:self];
// If the observed object does the post when thread A is here,
// you'll be fine since the observation has been removed.
}
这不是主线程对象,因为只观察其他主线程对象,定义一个问题,你不能进入我所描述的线程A和B的场景。
对于多线程的情况下,只有这样才能保证你会避免这些问题是确保观察者的引用计数击中0 之前,如果有人负责观察的生命周期的观测站(即你有任何形式的term
或close
方法)很容易。 如果没有,我不知道一个解决方案。