Beginnen wir mit retain
und release
; autorelease
ist wirklich nur ein Sonderfall, wenn Sie die Grundkonzepte verstanden haben.
In Cocoa verfolgt jedes Objekt, wie oft auf es verwiesen wird (insbesondere NSObject
implementiert die Basisklasse dies). Wenn Sie retain
ein Objekt aufrufen , teilen Sie ihm mit, dass Sie seine Referenzanzahl um eins erhöhen möchten. Durch Aufrufen release
teilen Sie dem Objekt mit, dass Sie es loslassen, und sein Referenzzähler wird dekrementiert. Wenn nach dem Aufruf release
der Referenzzähler jetzt Null ist, wird der Speicher dieses Objekts vom System freigegeben.
Der einfachste Weg , dies unterscheidet sich von malloc
und free
ist , dass eine bestimmte Aufgabe nicht über andere Teile des Systems zu sorgen braucht abstürzt , weil Sie Speicher freigegeben haben sie verwendet haben . Angenommen, jeder spielt mit und behält / gibt gemäß den Regeln frei. Wenn ein Code das Objekt behält und dann freigibt, bleibt jeder andere Code, der ebenfalls auf das Objekt verweist, unberührt.
Was manchmal verwirrend sein kann, ist zu wissen, unter welchen Umständen Sie anrufen sollten retain
und release
. Meine allgemeine Faustregel lautet: Wenn ich längere Zeit an einem Objekt festhalten möchte (z. B. wenn es sich um eine Mitgliedsvariable in einer Klasse handelt), muss ich sicherstellen, dass die Referenzanzahl des Objekts über mich Bescheid weiß. Wie oben beschrieben, wird der Referenzzähler eines Objekts durch Aufrufen erhöht retain
. Konventionell wird es auch erhöht (wirklich auf 1 gesetzt), wenn das Objekt mit einer "init" -Methode erstellt wird. In beiden Fällen liegt es in meiner Verantwortung, release
das Objekt aufzurufen, wenn ich damit fertig bin. Wenn ich das nicht tue, wird es einen Speicherverlust geben.
Beispiel für die Objekterstellung:
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
Nun zu autorelease
. Die Autorelease wird als bequeme (und manchmal notwendige) Methode verwendet, um das System anzuweisen, dieses Objekt nach einer Weile freizugeben. Aus Sanitärsicht autorelease
wird der aktuelle Thread NSAutoreleasePool
beim Aufruf über den Anruf informiert. Das NSAutoreleasePool
weiß jetzt, dass es release
das Objekt aufrufen kann, sobald es eine Gelegenheit erhält (nach der aktuellen Iteration der Ereignisschleife) . Aus unserer Sicht als Programmierer kümmert es sich darum, release
uns anzurufen, also müssen wir nicht (und sollten es auch nicht).
Was Anmerkung Wichtig ist , dass (wieder durch Konvention) alle Objekterstellung Klasse Methoden geben ein Autoreleased Objekt. Im folgenden Beispiel hat die Variable "s" beispielsweise einen Referenzzähler von 1, der jedoch nach Abschluss der Ereignisschleife zerstört wird.
NSString* s = [NSString stringWithString:@"Hello World"];
Wenn Sie an dieser Zeichenfolge festhalten möchten, müssen Sie sie retain
explizit aufrufen und dann explizit release
, wenn Sie fertig sind.
Betrachten Sie den folgenden (sehr erfundenen) Code, und Sie werden eine Situation sehen, in der dies autorelease
erforderlich ist:
- (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];
}
Mir ist klar, dass dies alles etwas verwirrend ist - irgendwann wird es jedoch klicken. Hier sind einige Referenzen, die Sie zum Laufen bringen:
- Apples Einführung in die Speicherverwaltung.
- Cocoa Programming für Mac OS X (4. Ausgabe) von Aaron Hillegas - ein sehr gut geschriebenes Buch mit vielen großartigen Beispielen. Es liest sich wie ein Tutorial.
- Wenn Sie wirklich eintauchen, können Sie zur Big Nerd Ranch gehen . Dies ist eine Schulungseinrichtung, die von Aaron Hillegas - dem Autor des oben genannten Buches - betrieben wird. Ich habe dort vor einigen Jahren den Intro to Cocoa-Kurs besucht und es war eine großartige Möglichkeit zu lernen.