2011-09-03 6 views
7

So che la gestione della memoria in iOS è complicata per i neofiti come me, ma speravo in una spiegazione chiara qui su StackOverflow che non riuscivo a trovare da nessun'altra parte.autorelease vs. release in dealloc

Quindi, far finta di avere una proprietà/ivar

@property(nonatomic, retain) UIPopoverController *popOver; 

che sto assegnando in questo modo:

self.popOver = [[[UIPopoverController alloc] initWithContentViewController:popOverContent] autorelease];  

Ora, nel mio dealloc e metodi viewDidUnload, che faccio sia

// in viewDidUnload: 
self.popOver = nil; 
// in dealloc: 
[popOver release]; 

Domanda:

  1. Se faccio nil/release in viewDidUnload/dealloc, ho davvero bisogno di autorelease all'assegnazione?
  2. Viceversa, se eseguo l'autorelease in fase di allocazione, è necessario annullare/rilasciare in un secondo momento?
  3. Qual è la differenza, se presente?

Grazie in anticipo per il vostro tempo - io continuerò a leggere, sul serio la gestione della memoria non può essere così difficile per avvolgere la testa in giro ...

+0

Grazie per aver modificato il titolo; Ho visto domande simili che avevano "iOS:" di fronte; in realtà è iniziato senza di esso. – pille

risposta

5

non essere confuso dal autorelease in questa linea:

self.popOver = [[[UIPopoverController alloc] initWithContentViewController:popOverContent] autorelease]; 

Dopo questa dichiarazione si possiede in modo efficace l'oggetto perché il setter di proprietà rivendicato la proprietà di esso. L'autorelease equilibra lo alloc-init.

Quindi ... sì, è necessario eseguire l'autorelease all'assegnazione. Se avete fatto queste cose (senza autorelease), si Leak:

self.popOver = [[UIPopoverController alloc] initWithContentViewController:popOverContent]; 

Un'altra opzione è quella di utilizzare una variabile temporanea invece di autorelease:

UIPopoverController *temp = [[UIPopoverController alloc] initWithContentViewController:popOverContent]; 
self.popOver = temp; 
[temp release]; 

In entrambi i casi è necessario rilasciare l'oggetto in dealloc.

+0

Grazie ad Abizern e Yuji anche per le loro risposte molto illuminanti. Inoltre ora ho capito l'idea di "proprietà locale" come descritto nella risposta di Yuji. In ogni caso, c'è un modo per testare la tua domanda di perdite di memoria (magari usando gli strumenti)? – pille

+0

@pille Sì, è possibile utilizzare [Strumenti] (http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Introduction/Introduction.html). In Xcode, [fai clic e tieni premuto il pulsante Esegui] (http://stackoverflow.com/questions/5305906/xcode-4-running-the-leaks-instrument) o seleziona [Prodotto -> Profilo] (http: // stackoverflow .com/domande/5304390/strumenti-in-Xcode-4). Questo fa apparire una finestra di dialogo in cui puoi scegliere "Perdite". – albertamg

+0

@pille Anche prima di usare Instruments, basta fare "Analyze", che è disponibile sotto il menu "Build" di XCode. – Yuji

4

1 Se faccio nil/rilascio in viewDidUnload/dealloc, ho davvero bisogno di autorelease all'assegnazione?

Sì.

2 Viceversa, se eseguo l'autorelease in fase di allocazione, è necessario annullare/rilasciare in un secondo momento?

Sì.

Nel primo caso, l'auto-rilascio viene effettuato per conto di tale metodo. Quel metodo non ha più bisogno del popover, quindi deve (automaticamente) rilasciarlo.

Al dealloc, il tuo oggetto non ha più bisogno del popover. Pertanto, è necessario rilasciarlo.

È molto semplice. Non è necessario considerare la proprietà dell'oggetto a lungo termine; devi solo pensare molto localmente, al livello di ogni metodo. La decisione di rilasciarlo o meno non dipende affatto dal fatto che quell'oggetto sia mantenuto da altre parti del programma. In un metodo, se si assegna un oggetto e non si ha più bisogno di esso in quel metodo, lo si (auto) lo rilascia.

Il dealloc è una leggera eccezione alla regola. Lì, è necessario rilasciare la proprietà di tutte le variabili di istanza.

Questo è tutto!

1
  1. Sì. Ma forse non in questo caso.
  2. Sì. Ma forse non in questo caso.
  3. viewDidUnload viene chiamato quando la vista viene scaricata, dealloc viene chiamato quando viene distrutta la vista Controller.

In viewDidUnload si rilascia oggetti utilizzati dal vista che non sono più necessario e può essere ricreato in viewDidLoad. Ovvio, dal momento che la vista non viene visualizzata, non è necessario mantenere gli oggetti impostati dal controller della vista.

In dealloc si pulisce il viewController e qui a chiarire tutte le sue risorse, compresi quelli che le ha assegnato la vista.

In questo caso, la vista non possiede il controller popover - dovrebbe essere di proprietà del controller della vista, quindi non c'è alcun bisogno di rilasciarlo in viewDidUnload ma si ha bisogno di rilasciarlo in dealloc.