在主线程上发布NSNotification

Run*_*oop 59 cocoa objective-c nsnotificationcenter ios

我发现以下代码片段允许NSNotification从任何后台线程发布在主线程上.我想知道这是否安全可接受?

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

Ano*_*dya 53

是的,你可以.

通常,您希望在主服务器上发送NSNotifications,特别是如果它们触发UI活动,例如解除模态登录对话框.

向特定线程发送通知

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

  • 在特定线程上发布通知正在对客户进行假设.我会在客户端发布通知并处理线程问题 (4认同)
  • NSDistributedNotificationCenter的文档与此相矛盾:"如果接收进程是多线程的,则不依赖于到达主线程的通知.通知通常会传递到主线程的运行循环,但其他线程也可以接收通知." (3认同)

Und*_*ndo 16

这是 - 您进入主线程并发布通知.不能比那更安全.

  • 但肯定这是糟糕的设计,你不知道什么会处理你的通知,因此不应该假设它应该传递给哪个线程.观察者应该处理通知并自己决定哪个线程是合适的. (17认同)

Whi*_*rCZ 14

Swift 2语法

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

Swift 3语法

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


Dan*_*ark 6

沿着这条线的某个地方,这可能是:

addObserver(forName:object:queue:using:)
Run Code Online (Sandbox Code Playgroud)

这是在这里,但重点是queue对象.

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

那么如何获得与主runloop对应的队列?

let mainQueue = OperationQueue.main

注意:这是在您订阅通知时,所以您只需执行一次即可完成通知.在每次通话中都这样做是非常多余的.