可以使用通知与 IOS 应用程序的主线程进行通信吗? (参见 performSelectorOnMainThread)

Posted

技术标签:

【中文标题】可以使用通知与 IOS 应用程序的主线程进行通信吗? (参见 performSelectorOnMainThread)【英文标题】:is it ok to use of a notification to communication back to the main thread of an IOS app? (cf performSelectorOnMainThread) 【发布时间】:2011-11-07 04:13:24 【问题描述】:

是否可以使用通知与 ios 应用程序的主线程进行通信? (参见 performSelectorOnMainThread)。也就是说,有没有为此目的的问题?

背景

想要从后台线程回调主 UI 线程(例如 performSelectorInBackground) 可以使用 performSelectorOnMainThread 进行通信,但想知道是否可以使用通知?

例如

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

【问题讨论】:

【参考方案1】:

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

来自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 指出的那样,一个更好的解决方案是让发送者在它决定的任何线程上发送通知,然后让侦听器负责使用适当的线程来执行它需要的任何操作。

希望对您有所帮助。

【讨论】:

我在回答的评论中引用了这个问题。我不喜欢发布通知的对象与观察者之间的耦合的完全 b/c 解决方案。对象张贴应该张贴在它喜欢的任何线程上。接收者应该在它需要的线程上处理通知(例如,接收者可以将通知转发到主线程或任何其他线程)。 Apple 在其示例代码中也使用了这种方法。 我完全同意。我已经更新了我的答案以反映这种方法。 @PixelCloudSt 我理解这种方法的耦合,但我该如何让接收器在多个线程上监听? @AlexGodbehere 侦听器无法指示它在哪个线程上接收消息。你最好的策略是在它进入的任何线程上接收消息(因为除非你想控制发送者,否则你别无选择),然后从接收者那里,在你希望的任何线程上执行你想要的任何操作使用。希望能回答您的问题。 [[NSOperationQueue mainQueue] addOperationWithBlock:^ ]; 通常是performSelectorOnMainThread: 的更干净的改动【参考方案2】:

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

【讨论】:

好的,谢谢 - 我遇到了一些问题 (***.com/questions/8032987/…),想知道这是否是原因 好的,刚刚发布了一个答案。我通常发现在处理程序中强制执行任何线程要求比在发送方更好。例如,您可以确保始终在主线程上发布通知,但这很乏味。发布对象不应该关心。收件人确实很在意,如果合适,应该将消息转发到主线程。

以上是关于可以使用通知与 IOS 应用程序的主线程进行通信吗? (参见 performSelectorOnMainThread)的主要内容,如果未能解决你的问题,请参考以下文章

iOS 应用程序可以通过 WiFi 与 MFi 配件通信吗?

多线程核心点

Java基础教程:多线程基础——线程间的通信

向 Cocoa 应用程序的主事件循环发布消息?

Android EventBus

IOS NSNotification Center 通知中心的使用