2011-11-07 15 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

相關問題