Cominciamo con retain
e release
; autorelease
è davvero solo un caso speciale una volta compresi i concetti di base.
In Cocoa, ogni oggetto tiene traccia di quante volte viene fatto riferimento (in particolare, la NSObject
classe base lo implementa). Richiamando retain
un oggetto, gli dici che vuoi aumentare il suo conteggio dei riferimenti di uno. Chiamando release
, comunichi all'oggetto che lo stai lasciando andare e il suo conteggio dei riferimenti viene diminuito. Se, dopo la chiamata release
, il conteggio dei riferimenti è ora zero, la memoria di quell'oggetto viene liberata dal sistema.
Il modo di base in cui questo è diverso malloc
ed free
è che un dato oggetto non deve preoccuparsi del crash di altre parti del sistema perché hai liberato la memoria che stavano usando. Supponendo che tutti stiano giocando e conservando / rilasciando secondo le regole, quando un pezzo di codice conserva e poi rilascia l'oggetto, qualsiasi altro pezzo di codice che fa riferimento all'oggetto non verrà influenzato.
Ciò che a volte può creare confusione è conoscere le circostanze in cui dovresti chiamare retain
e release
. La mia regola generale è che se voglio rimanere aggrappato a un oggetto per un certo periodo di tempo (se si tratta di una variabile membro in una classe, per esempio), allora devo assicurarmi che il conteggio dei riferimenti dell'oggetto sappia di me. Come descritto sopra, il conteggio dei riferimenti di un oggetto viene incrementato chiamando retain
. Per convenzione, viene anche incrementato (impostato a 1, in realtà) quando l'oggetto viene creato con un metodo "init". In entrambi i casi, è mia responsabilità richiamare release
l'oggetto quando ho finito. Se non lo faccio, ci sarà una perdita di memoria.
Esempio di creazione di oggetti:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Adesso per autorelease
. Autorelease è usato come un modo comodo (e talvolta necessario) per dire al sistema di liberare questo oggetto dopo un po 'di tempo. Dal punto di vista idraulico, quando autorelease
viene chiamato, il thread corrente NSAutoreleasePool
viene avvisato della chiamata. L' NSAutoreleasePool
ora sa che una volta che si ottiene l'opportunità (dopo l'iterazione corrente del ciclo di eventi), si può chiamare release
sull'oggetto. Dal nostro punto di vista di programmatori, si prende cura di release
chiamarci, quindi non dobbiamo (e in effetti, non dovremmo).
Ciò che è importante notare è che (di nuovo, per convenzione) tutta la creazione di oggetti metodi della classe di restituiscono un oggetto rilasciato automaticamente. Ad esempio, nel seguente esempio, la variabile "s" ha un conteggio dei riferimenti pari a 1, ma una volta completato il ciclo di eventi, verrà distrutto.
NSString* s = [NSString stringWithString:@"Hello World"];
Se vuoi aggrapparti a quella stringa, devi chiamarla retain
esplicitamente e poi esplicitamente release
quando hai finito.
Considera il seguente bit di codice (molto artificioso) e vedrai una situazione in cui autorelease
è richiesto:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Mi rendo conto che tutto questo crea un po 'di confusione, ma a un certo punto farà clic. Ecco alcuni riferimenti per iniziare:
- Introduzione di Apple alla gestione della memoria.
- Cocoa Programming per Mac OS X (4a edizione) , di Aaron Hillegas - un libro molto ben scritto con molti ottimi esempi. Sembra un tutorial.
- Se ti stai davvero immergendo, potresti andare al Big Nerd Ranch . Questa è una struttura di formazione gestita da Aaron Hillegas, l'autore del libro sopra menzionato. Ho frequentato il corso Intro to Cocoa lì diversi anni fa ed è stato un ottimo modo per imparare.