2011-11-07 5 views
13

Va bene utilizzare una notifica per la comunicazione sul thread principale di un'app IOS? (cf performSelectorOnMainThread). Cioè, ci sono dei gottcha per questo scopo?è consentito l'uso di una notifica per la comunicazione sul thread principale di un'app IOS? (cf performSelectorOnMainThread)

Sfondo

  • desidera richiamare al thread UI principale da un thread in background (ad esempio performSelectorInBackground)
  • potrebbe usare performSelectorOnMainThread per comunicare indietro, ma chiedo se è OK per utilizzare una notifica?

Ad esempio

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

risposta

20

In realtà c'è un gottcha; ti fermerai a caso! Questa è stata la mia esperienza. Ciò ha a che fare con il fatto che l'oggetto che riceve la notifica lo fa sullo stesso thread del mittente della notifica.

Dal Apple iOS Documentation on Notification Centers:

In un'applicazione multithreading, le notifiche vengono sempre consegnati in thread in cui è stata pubblicata la notifica, che non può essere lo stesso filo in cui un osservatore stesso iscritto.

Questo ti causerà inevitabilmente mal di testa.

Se la notifica viene ricevuta da qualcosa sul thread principale, ho scoperto che il popping nel thread principale dal thread in background per emettere una notifica è il modo più sicuro per farlo. E 'abbastanza semplice da fare:

//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]; 
} 

Purtroppo questo introduce una sottile accoppiamento tra il mittente e il destinatario in che si sta modificando il mittente per ospitare il ricevitore.

Una soluzione ancora migliore, come sottolinea XJones, è far sì che il mittente invii la notifica su qualsiasi thread a cui decide, e quindi fare in modo che il listener sia responsabile dell'utilizzo del thread appropriato per eseguire qualsiasi azione necessaria.

Spero che sia stato utile.

+1

Ho fatto riferimento a questo problema in un commento nella mia risposta. Non mi piace la tua soluzione esattamente b/c dell'accoppiamento tra l'oggetto che invia la notifica e l'osservatore. La pubblicazione dell'oggetto dovrebbe pubblicare su qualsiasi thread che gli piace. Il ricevitore deve gestire la notifica sul thread di cui ha bisogno (ad esempio il destinatario può inoltrare la notifica al thread principale o qualsiasi altro thread). Apple usa questo metodo anche nel suo codice di esempio. – XJones

+0

Sono completamente d'accordo. Ho aggiornato la mia risposta per riflettere questo metodo. – PixelCloudSt

+0

@PixelCloudSt Capisco l'accoppiamento in questo metodo, ma come farei per far sì che il ricevitore ascolti su più thread? –

8

Sì, notifiche possono essere utilizzati per questo scopo. puoi usare qualsiasi metodo che ti piace (protocolli, notifiche, messaggistica diretta) per comunicare tra oggetti attraverso i thread. Quello che scegli dipende da ciò che ritieni più appropriato. Le notifiche sono grandi quando l'oggetto che invia la notifica non sa nulla degli oggetti che osservano la notifica. Se si invia un messaggio (ad esempio performSelectorOnMainThread), l'oggetto che invia il messaggio deve conoscere l'oggetto a cui invia il messaggio (in genere tramite un protocollo).

+0

ok grazie - Ho avuto alcuni problemi (http://stackoverflow.com/questions/8032987/why-do-i-get-wait-fences-failed-to-receive-reply-for-this-code) e mi chiedevo se questo potesse essere il motivo – Greg

+1

ok, ho appena postato una risposta su quello. Generalmente trovo che sia meglio applicare i requisiti di thread nei gestori vs al mittente. Ad esempio, puoi assicurarti di pubblicare sempre le notifiche sul thread principale, ma questo è noioso. L'oggetto di pubblicazione non dovrebbe interessare.Il destinatario si cura e dovrebbe inoltrare il messaggio al thread principale, se necessario. – XJones