NSNotificationCenter和安全的多线程(NSNotificationCenter a

2019-07-04 15:56发布

鉴于对象可能即使在方法调用过程中(被释放链接 )*,它是安全的对象注册并接收将在一个线程,是从它预计将在一个不同的交付通知释放?

作为参考, 文档指出,

在多线程应用程序,通知始终在该通知被张贴线程,这可能不是由观察者本身注册在同一个线程交付。

同样重要的是,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之前:返回,最后强大的参考对象(在代码中,我可以看到)被打破了。

  1. 我在想,纠正:

    一个。 如果NSNotificationCenter调用-handleNotification之前需要一个强大的参考对象:在其上,那么对象将不会被释放,直到-handleNotification后:回报,

    湾 如果NSNotificationCenter不调用-handleNotification之前采取强有力的参考对象:在其上,那么对象可-handleNotification之前释放:回报

  2. 哪种方式(A或B),它的工作原理? 我还没有发现这个话题在文档中尚未覆盖,但它似乎在多线程环境中安全使用NSNotificationCenter比较重要。

更新:在上述环节的答案被更新表示“ARC保留并围绕弱引用调用释放”。 这意味着,当一个方法调用正在进行的对象不应该被释放。

Answer 1:

我一直建议,如果你看到通知上不是主要的其他线程飞来飞去,和你看到的释放操作发生在后台,你的线程可能是太复杂了。 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:]返回充当观察者的不透明对象。 你必须跟踪这个对象,这样你以后可以删除观察者。



Answer 2:

NSNotificationCenter不采取强有力的参考对象,因此,观察者必须释放之前被删除。 当ARC被启用,如果被调用的handleNotification,观察者也不会因为调用的handleNotification将增加其保留计数释放。 如果通知发布之前观察员被释放,NSNotificationCenter将与您在dealloc方法写,这样的handleNotification不会被调用从观察者将其删除。 NSNotificationCenter而通知发布同步调用通知处理程序。



文章来源: NSNotificationCenter and safe multithreading