Cominciamo con retaine 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 NSObjectclasse base lo implementa). Richiamando retainun 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 malloced 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 retaine 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 releasel'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 autoreleaseviene chiamato, il thread corrente NSAutoreleasePoolviene avvisato della chiamata. L' NSAutoreleasePoolora sa che una volta che si ottiene l'opportunità (dopo l'iterazione corrente del ciclo di eventi), si può chiamare releasesull'oggetto. Dal nostro punto di vista di programmatori, si prende cura di releasechiamarci, 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 retainesplicitamente e poi esplicitamente releasequando 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.