2011-11-07 60 views
13

使用通知回传给IOS应用程序的主线程可以吗? (参看performSelectorOnMainThread)。也就是说,这里有什么gottcha?是否可以使用通知返回到iOS应用程序的主线程? (比较performSelectorOnMainThread)

背景

  • 想打电话回主UI线程从后台线程(例如performSelectorInBackground)
  • 可以使用performSelectorOnMainThread沟通回来,但不知道是否它是确定使用通知?

例如

[[NSNotificationCenter defaultCenter] postNotificationName:@"ModelChanged" object:self]; 

回答

20

其实有一个gottcha;你会随机崩溃!这是我的经验。这与接收通知的对象在与通知的发送者相同的线程上这样做的事实有关。

Apple iOS Documentation on Notification Centers

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

这将不可避免地令你头疼。

如果通知正在被主线程上的某些东西接收到,我发现从后台线程弹出进入主线程发出通知是最安全的方法。这是做的相当简单:

//Call this to post a notification and are on a background thread  
- (void) postmyNotification{ 
    [self performSelectorOnMainThread:@selector(helperMethod:) withObject:Nil waitUntilDone:NO]; 
} 

//Do not call this directly if you are running on a background thread. 
- (void) helperMethod{ 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"SOMENAME" object:self]; 
} 

不幸的是这引入了发送者和接收者之间的微妙耦合在正在修改的发送者,以适应接收器。正如XJones指出的,更好的解决方案是让发送者发送通知给它所决定的任何线程,然后让侦听器负责使用正确的线程执行所需的任何操作。

希望有帮助。

+1

我在回答中的评论中引用了此问题。我不喜欢你的解决方案完全是发布通知的对象与观察者之间的耦合的b/c。对象发布应该发布在它喜欢的任何线程上。接收者应该在它需要的线程上处理通知(例如,接收者可以将通知转发给主线程或任何其他线程)。 Apple在其示例代码中也使用这种方法。 – XJones

+0

我完全同意。我已更新我的答案以反映此方法。 – PixelCloudSt

+0

@PixelCloudSt我明白这种方法中的耦合,但我将如何去让接收器在多线程上进行侦听? –

8

是的,通知可以用于此目的。您可以使用任何您喜欢的方法(协议,通知,直接消息传递)在跨线程的对象之间进行通信。你选择哪一个取决于你认为最合适的。当发布通知的对象不了解观察通知的对象时,通知非常棒。如果您发送消息(例如performSelectorOnMainThread),则发送消息的对象确实需要知道它正在发送消息的对象(通常是通过协议)。

+0

好的谢谢 - 我有一些问题(http://stackoverflow.com/questions/8032987/why-do-i-get-wait-fences-failed-to-receive-reply-for-this-code )并想知道这是否可能是 – Greg

+1

好的原因,只是发布了一个答案。我通常发现在处理程序和发件人处强制执行任何线程要求会更好。例如,您可以确保始终在主线程上发布通知,但这很乏味。发布对象不应该在意。收件人确实在意并且应该将消息转发给主线程。 – XJones

相关问题