2009-06-16 19 views
9

Ho visto il codice (probabilmente il codice di esempio di Apple) scritto in modo tale da rilasciare ivar in dealloc e impostare la proprietà in viewDidUnload.È necessario rilasciare l'ivar e impostare l'ivar sintetizzato su zero allo stesso tempo?

ad es.

- (void)viewDidUnload 
{ 
    self.navigationController = nil; 
} 

- (void)dealloc 
{ 
    [_navigationController release]; 
} 

Perché li fanno in due posti? Inoltre, perché impostare nil in uno e rilasciarne un altro. Sembra che self.property = nil si prenda cura di tutto dato che rilasciare e impostare l'ivar su zero.

risposta

5

Hai ragione: puoi davvero fare self.property = nil ovunque, incluso dealloc. L'unico svantaggio è che se il metodo setter fa qualcosa di più complicato del semplice rilascio di ivar, potresti tentare di accedere ad altri campi che sono già stati rilasciati, ecc.

Per quanto riguarda il motivo per cui rilascia anche la presa in viewDidUnload , questa è un'ottimizzazione della memoria. Dato che le cose che hai rilasciato in viewDidUnload sono cose che verranno ripristinate quando la vista viene caricata di nuovo, rilasciandole libera la memoria in situazioni di memoria insufficiente.

+0

Grazie, quindi in questo caso il codice viewDidUnload avrebbe potuto essere utilizzato lo stesso codice dealloc per rilasciare l'oggetto, vale a dire [rilascio _navigationController] piuttosto che impostarlo su zero, giusto? – Boon

+1

Sì, ma non farlo. Usa l'accessorio ovunque tranne in -dealloc. L'uso degli accessor in -dealloc è controverso per le ragioni che ha dato Daniel (Apple non è chiara su cosa raccomandano, anche). Prendi l'abitudine di liberare tutti i tuoi ivar conservati in -dealloc. Non scommettere su qualche altra cosa per farlo per te. E ogni volta che rilasci qualcosa, mettilo a zero. Gran parte di ObjC è senza una rete di sicurezza; le buone abitudini sono ciò che fa funzionare i tuoi programmi perché il compilatore non ti salverà. (OK, forse Clang ci salverà, ma useremo la sua energia per sempre.) –

0

Se vi affidate ai garbage collection (disponibile in Objective-C 2.0) quindi impostando il ivar-nil e chiamando release otterrà lo stesso fine.

Immagino che il codice che stai guardando gestisca la memoria con release e lo imposti su nil in modo da non provare più tardi ad accedere ad un oggetto che non c'è più. Il nil è più contabile rispetto alla gestione della memoria quando non si sta facendo affidamento sul GC.

+0

Non proprio - - [versione anObject] non farà nulla (è un nocciolo) sotto GC, mentre l'impostazione a nil consentirà al garbage collector per liberare finalmente l'oggetto (sta rimuovendo un riferimento), a meno che l'ivar non sia definito come riferimento debole. – xtophyr

1

Apple consiglia di non chiamare setter nelle routine init e in particolare dealloc.

Ciò è dovuto al fatto che l'oggetto è solo parzialmente impostato in questo momento, e i setter potrebbero avere osservatori collegati a loro, o potrebbero essere sovrascritti da sottoclassi, e altrimenti avere effetti indesiderati durante dealloc, o potrebbero essere confusi durante init con un oggetto parzialmente configurato.

Quindi, normalmente si usa:

_navigationController = [[NavController alloc] init]; 

codice di stile nella vostra routine init, codice

[_navigationController release]; 

stile nella vostra dealloc, e setter in altro codice in cui l'oggetto è noto per essere pienamente completare.

Alcuni casi da considerare:

  • sottoclasse sovrascrive setNavigationController e riferimenti propri ivars assegnati da init. Crash su init.
  • Sottoclasse sovrascrive setNavigationController e fa riferimento ai propri ivars rilasciati in dealloc. Crash su dealloc.
  • Sottoclassi sostituisce setNavigationController e ridisegna alcune parti dello schermo. Spreco di cicli inutile o display difettoso.
  • Altri oggetti essendo deallocati contemporaneamente osservare navigationController e quegli osservatori aziona durante dealloc
  • ecc
Problemi correlati