2012-04-06 1 views
16

io di solito uso NSNotification come l'esempio riportato di seguito:Che è un modo migliore per rimuovere Notifica osservatore

In viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(foo:) name:kName1 object:nil]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bar:) name:kName2 object:nil]; 

In viewDidUnload e dealloc:

[[NSNotificationCenter defaultCenter] removeObserver:self]; 

Ma un amico mi ha detto che non dovrei usare [[NSNotificationCenter defaultCenter] removeObserver:self]; perché rimuoverà tutti gli osservatori inclusa la super classe. Mi ha suggerito di usare il seguente codice per rimuovere uno per uno gli osservatori.

[[NSNotificationCenter defaultCenter] removeObserver:self name:kName1 object:nil]; 
[[NSNotificationCenter defaultCenter] removeObserver:self name:kName2 object:nil]; 

ho controllato il codice della libreria ASIHttpRequest (https://github.com/pokeb/asi-http-request). Segue il suggerimento dei miei amici.

Voglio sapere se il mio amico ha ragione o no? Secondo me, dato che l'istanza attuale verrà scaricata o dealloc, anche la notifica della super classe è inutile. E c'è qualche sistema che la sottoclasse UIViewController usi?

+0

Che cosa significa rimuovere l'osservatore di "super classe"? Un osservatore è un'istanza di oggetto non una classe. Se verrà deallocato, sarà necessario annullare la registrazione di tutte le notifiche, anche se sono state registrate nel codice di super classe. – MrTJ

+0

@MrTJ Intendo l'osservatore delle notifiche che viene aggiunto nel metodo di super. Forse il padre dell'istanza di classe deve anche osservare alcune notifiche quando viene chiamato il metodo viewDidUnload di child. – tangqiaoboy

+0

Potrebbe essere, potrebbe essere.Se si desidera annullare la registrazione in viewDidUnload, quindi per sicurezza, suggerisco di utilizzare il secondo metodo (senza registrazione degli osservatori) – MrTJ

risposta

12

Il tuo amico è corretto al 100%. Tuttavia, non importa se rimuovi tutte le osservazioni di notifica in dealloc.
Hai menzionato viewDidUnload e il caso è completamente diverso, perché l'oggetto scaricato rimane attivo e non sai quando vengono aggiunte nuovamente le osservazioni di notifica della superclasse. Se vengono aggiunti in viewDidLoad non avrai problemi. Se vengono aggiunti in un metodo di init, hai appena perso un sacco di importanti osservazioni di notifica.

La rimozione di osservazioni con nomi specifici è una buona pratica e dovrebbe essere eseguita sin dall'inizio.

+0

Grazie. Quindi possiamo usare '[[NSNotificationCenter defaultCenter] removeObserver: self];' nel metodo 'dealloc', ma NON nel metodo' viewDidUnload', giusto? – tangqiaoboy

+0

Sì, 'removeObserver:' non dovrebbe essere usato al di fuori di dealloc. Ma mi piace rimuovere ogni osservazione in modo specifico me stesso, quindi non uso affatto "removeObserver:". Io uso il metodo specifico 'removeObserver: name: object:' per tutte le mie notifiche. Mi piace mantenere il mio codice molto specifico. –

7

Quando si desidera rimuovere tutte le notifiche si utilizza,

[[NSNotificationCenter defaultCenter] removeObserver:self]; 

Se si desidera rimuovere una notifica particolare si utilizza,

[[NSNotificationCenter defaultCenter] removeObserver:self name:kName1 object:nil]; 

Quando non è più bisogno di alcuna notifica del primo l'approccio è semplice.

0

Io uso la prima, non ho mai pensato se fosse giusto o no. Se dealloc viene chiamato, l'oggetto (super pure) sarà comunque deallocato. Quello che NON VUOI assolutamente è che NSNotification sia inviato ad un'istanza deallocata.

1

Come l'oggetto sta andando via, è sicuro di utilizzare [[NSNotificationCenter defaultCenter] removeObserver:self]; nel metodo dealloc.

Nel metodo ViewDidUnload, è meglio rimuovere ogni osservatore uno per uno come riferimento al controller ancora in giro (e il corrispondente viewDidLoad dovrebbe aggiungerli tutti nuovamente).