Risposte:
Oltre a quanto già indicato, ho voluto approfondire la logica sottostante -viewDidUnload
.
Uno dei motivi più importanti per l'implementazione è che le UIViewController
sottoclassi comunemente contengono anche riferimenti di proprietà a varie sottoview nella gerarchia della vista. Queste proprietà potrebbero essere state impostate IBOutlets
durante il caricamento da un pennino o in modo programmatico all'interno -loadView
, ad esempio.
La proprietà aggiuntiva delle viste secondarie UIViewController
significa che anche quando la sua vista viene rimossa dalla gerarchia della vista e rilasciata per risparmiare memoria, attraverso la quale anche le viste secondarie vengono rilasciate dalla vista, non verranno effettivamente deallocate perché la UIViewController
stessa contiene ancora il proprio in sospeso mantenendo i riferimenti anche a quegli oggetti. Il rilascio della UIViewController
proprietà aggiuntiva di questi oggetti garantisce che verranno deallocati anche per liberare memoria.
Gli oggetti che rilasci qui vengono solitamente ricreati e impostati di nuovo quando la UIViewController
vista è re-loaded
, da un pennino o tramite un'implementazione di -loadView
.
Notare inoltre che la UIViewController
view
proprietà è nil
quando viene chiamato questo metodo.
Come dice la documentazione :
Viene chiamato durante le condizioni di memoria insufficiente quando il controller della vista deve rilasciare la sua vista e tutti gli oggetti associati a quella vista per liberare memoria.
Nella stessa situazione nondealloc
viene chiamato. Questo metodo è disponibile solo in OS3 e versioni successive. Affrontare la stessa situazione in iPhone OS 2.x è stato un vero dolore!
Aggiornamento luglio 2015 : va notato che è viewDidUnload
stato deprecato in iOS 6 perché "le visualizzazioni non vengono più eliminate in condizioni di memoria insufficiente e quindi questo metodo non viene mai chiamato". Quindi, il consiglio moderno è di non preoccuparsene e di usarlo dealloc
.
Questo perché tipicamente imposterai @property
come "(nonatomic, retain)"
e come tale il setter creato per te rilascia l'oggetto corrente e quindi mantiene l'argomento ie
self.property = nil;
... fa qualcosa sulla falsariga di:
[property release];
property = [nil retain];
Quindi stai uccidendo due piccioni con una fava: gestione della memoria (rilasciando l'oggetto esistente) e assegnando il puntatore a zero (poiché l'invio di qualsiasi messaggio a un puntatore zero restituirà zero).
Spero che aiuti.
Ricorda che viewDidUnload
è un metodo nel controller della vista, non nella vista. Il metodo della vista dealloc
verrà chiamato quando la vista viene scaricata, ma il metodo del controller della vista dealloc
potrebbe non essere chiamato se non in un secondo momento.
Se ricevi un avviso di memoria insufficiente e la tua vista non viene visualizzata, cosa che accadrà ad esempio ogni volta che utilizzi un UIImagePickerController per consentire all'utente di scattare una foto, la tua vista verrà scaricata e dovrà essere ricaricata dopo.
Conclusione:
I controller di visualizzazione hanno una proprietà di visualizzazione. In genere un pennino o un pezzo di codice aggiunge altre visualizzazioni a questa visualizzazione. Questo accade spesso all'interno di un metodo -viewDidLoad, come questo:
- (void)viewDidLoad {
[super viewDidLoad];
[self createManyViewsAndAddThemToSelfDotView];
}
inoltre, un file pennino può creare un pulsante e aggiungerlo alla vista del controller di visualizzazione.
Su iPhone OS 2.2, quando -didReceiveMemoryWarning veniva invocato dal sistema, dovevi rilasciare qualcosa per liberare memoria. Potresti rilasciare la visualizzazione dell'intero controller della vista se avesse senso. O solo grandi contenuti che consumano memoria.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
Ora, nel nuovo OS 3.0, c'è un metodo -viewDidUnload, che verrà richiamato dal sistema quando la vista è stata scaricata a causa della memoria insufficiente (correggimi: quando viene chiamato esattamente?)
-viewDidUnload viene utilizzato per rilasciare tutti gli oggetti che erano di proprietà sia del controller della vista stesso che della vista. Il motivo: se un controller di visualizzazione contiene riferimenti a elementi secondari della visualizzazione, ad esempio un pulsante, le visualizzazioni secondarie a cui si fa riferimento non verranno rilasciate, perché il loro numero di conservazione è> = 1. Dopo che sono state rilasciate in -viewDidUnload, possono essere liberate dalla memoria.
Apple ha deprecato viewWillUnload, ora dovresti usare didReceiveMemoryWarning o dealloc per rilasciare i tuoi oggetti.
In iOS 6, i metodi viewWillUnload e viewDidUnload di UIViewController sono ora deprecati. Se stavi usando questi metodi per rilasciare i dati, usa invece il metodo didReceiveMemoryWarning. È inoltre possibile utilizzare questo metodo per rilasciare riferimenti alla vista del controller di visualizzazione se non viene utilizzato. Dovresti verificare che la vista non sia in una finestra prima di farlo.
Se il controller di visualizzazione viene estratto dallo stack del controller di navigazione e non viene mantenuto altrove, verrà deallocato e verrà chiamato dealloc invece di viewDidUnload. Dovresti rilasciare le viste create in loadView in dealloc, ma non è necessario impostare le variabili a zero, perché subito dopo aver chiamato dealloc le variabili non esisteranno più.