在主线程上发布NSNotification


70

我发现了以下代码片段,该片段允许NSNotification从任何后台线程发布到主线程上。我想知道这是否是一种安全且可以接受的做法?

dispatch_async(dispatch_get_main_queue(),^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ImageRetrieved" 
                                                        object:nil 
                                                      userInfo:imageDict];
});

是的,这是安全且可以接受的。可用在IOS 4.0及更高版本:developer.apple.com/library/ios/documentation/Performance/...
Snowcrash

Answers:


61

是的,你可以

通常,您希望NSNotifications在主体上发送,尤其是当它们触发UI活动(例如关闭模式登录对话框)时,尤其如此。

将通知传递到特定线程

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


3
NSDistributedNotificationCenter的文档与此矛盾:“如果接收进程是多线程的,则不依赖于到达主线程的通知。该通知通常传递到主线程的运行循环,但其他线程也可以接收该通知。”
zoom23 2013年

@ zoom23:即使我发布的摘录也来自Apple文档。
Anoop Vaidya

我想知道为什么Apple自己的通知是在任意线程(例如ALAssetsLibraryChangedNotification)上传递的。在接收器对象上选择线程是更好的做法吗?
里维拉2014年

4
在特定线程上发布通知正在对客户端进行假设。我会在客户端发布通知并处理线程问题
Matt

这一切都发生了变化,因为您现在可以OperationQueue按照我在下面所说的进行选择stackoverflow.com/a/42800900/8047
Dan Rosenstark

17

这是-您正在进入主线程并发布通知。没有比这更安全的了。


18
但是肯定这是错误的设计,您不知道将处理您的通知的内容,因此不应假设应该在哪个线程上传递通知。观察者应处理该通知,并自行决定哪个线程合适。
马特

@matt正确的方法是在订户一方。您NotificationCenter有时可以使用它,有时甚至在文档中也称它为NSNotificationCenter
Dan Rosenstark

如果仅将mainQueue调用添加到选择器方法中,这会很容易吗?@Matt,这就是您要指向的内容吗?
nr5

15

Swift 2语法

dispatch_async(dispatch_get_main_queue()) {
    NSNotificationCenter.defaultCenter().postNotificationName("updateSpinner", object: nil, userInfo: ["percent":15])
}

Swift 3语法

DispatchQueue.main.async {
    NotificationCenter.default.post(name: "updateSpinner", object: nil, userInfo: ["percent":15])
}

12

通过以下方式可以实现:

addObserver(forName:object:queue:using:)

这是在这里,但整个点是queue对象。

应该添加块的操作队列。如果您通过nil,则该块将在发布线程上同步运行。

那么,如何获得与主运行循环相对应的队列?

let mainQueue = OperationQueue.main

注意:这是您订阅通知的时间,因此只需执行一次就可以了。在每个电话上都这样做非常多余。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.