鉴于对象可能即使在方法调用过程中(被释放链接 )*,它是安全的对象注册并接收将在一个线程,是从它预计将在一个不同的交付通知释放?
作为参考, 文档指出,
在多线程应用程序,通知始终在该通知被张贴线程,这可能不是由观察者本身注册在同一个线程交付。
同样重要的是,NSNotificationCenter不保留的强引用注册到接收通知的对象。
下面是可能使局势更加具体的例子:
- (id)init {
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:SomeNotification object:nil];
}
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)handleNotification:(NSNotification *)notification {
// do something
}
这个实现的对象接收SomeNotification上线十-handleNotification之前:返回,最后强大的参考对象(在代码中,我可以看到)被打破了。
我在想,纠正:
一个。 如果NSNotificationCenter调用-handleNotification之前需要一个强大的参考对象:在其上,那么对象将不会被释放,直到-handleNotification后:回报,
湾 如果NSNotificationCenter不调用-handleNotification之前采取强有力的参考对象:在其上,那么对象可-handleNotification之前释放:回报
哪种方式(A或B),它的工作原理? 我还没有发现这个话题在文档中尚未覆盖,但它似乎在多线程环境中安全使用NSNotificationCenter比较重要。
更新:在上述环节的答案被更新表示“ARC保留并围绕弱引用调用释放”。 这意味着,当一个方法调用正在进行的对象不应该被释放。
我一直建议,如果你看到通知上不是主要的其他线程飞来飞去,和你看到的释放操作发生在后台,你的线程可能是太复杂了。 ObjC是不是一个线程快乐的语言。 多数线程工作应该是在队列短命块的形式。 他们可以发布通知回主线程容易,但不应该经常食用通知。
这就是说,今天来管理多线程通知的最好办法是addObserverForName:object:queue:usingBlock:
这可以让你在有生之年更大的控制权。 这个模式应该是这个样子:
__weak id weakself = self;
id notificationObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:...
object:...
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note){
id strongself = weakself;
if (strongself) {
[strongself handleNotification:note];
}
}];
注意使用weakself / strongself的。 我们避免使用weakself保留循环。 当我们回来,我们采取强硬的参考第一。 如果我们仍然存在,那么我们就锁定在该块的其余部分(所以我们不能在dealloc中handleNotification:
如果不存在,则该通知将被丢弃。 (注意,弱引用调用之前有效归零dealloc
见objc_loadWeak 。)我使用mainQueue
这里,但你肯定可以使用另一个队列。
在“旧时代”(前10.6),我设计了解决此问题,通过控制对象的寿命。 基本上,我设计了这样短命的对象根本不听,可能来自其他线程的通知。 这比听起来要容易得多,因为在前期10.6码,线程可以保持相当罕见(和国际海事组织,仍然应该保持一个较低的水平)。 NSNotificationCenter
被设计为低线程的世界。
另外请注意,不像-[NSNotificationCenter addObserver:selector:name:object:]
, -[NSNotificationCenter addObserverForName:object:queue:usingBlock:]
返回充当观察者的不透明对象。 你必须跟踪这个对象,这样你以后可以删除观察者。
NSNotificationCenter不采取强有力的参考对象,因此,观察者必须释放之前被删除。 当ARC被启用,如果被调用的handleNotification,观察者也不会因为调用的handleNotification将增加其保留计数释放。 如果通知发布之前观察员被释放,NSNotificationCenter将与您在dealloc方法写,这样的handleNotification不会被调用从观察者将其删除。 NSNotificationCenter而通知发布同步调用通知处理程序。