Frage

Ich bin erst am Anfang, um einen Blick auf Objective-C und Cocoa-mit Blick auf das Spiel mit dem iPhone SDK.Ich bin Recht wohl mit C malloc und free Konzept, aber Kakao Referenzen zählen Schema hat mich ziemlich verwirrt.Ich hab gesagt, es ist sehr elegant sobald Sie es verstehen, aber ich bin einfach nicht über den Berg noch.

Wie release, retain und autorelease Arbeit und was sind die Konventionen über deren Gebrauch?

(Oder, ansonsten, was haben Sie Lesen, die geholfen haben Sie es bekommen?)

War es hilfreich?

Lösung

Beginnen wir mit retain und release; autorelease ist eigentlich nur ein besonderer Fall, sobald Sie verstehen, die grundlegenden Konzepte.

In Kakao, jedes Objekt verfolgt, wie oft Sie referenziert wird (insbesondere die NSObject Basisklasse implementiert).Durch den Aufruf retain auf ein Objekt, sagen Sie, dass Sie es wollen, bis Ihr Referenzzähler um eins.Durch den Aufruf release, Sie sagen, das Objekt, das Sie sind, es loszulassen, und dessen Referenzzähler dekrementiert.Wenn, nach dem Aufruf release, die referenzzahl ist jetzt null ist, dann wird das Objekt Speicher wird freigegeben, indem der system.

Der einfachste Weg, dies unterscheidet sich von malloc und free ist, dass ein Objekt nicht brauchen, um sorgen über andere Teile der system abstürzt, weil Sie haben, befreit Speicher, den Sie verwenden.Vorausgesetzt, alle spielen zusammen und binden/lösen nach den Regeln, wenn ein Stück code behält und gibt dann das Objekt, jedes andere Stück code auch die Verweise auf das Objekt unberührt.

Was können manchmal verwirrend sein, ist die Kenntnis der Umstände, unter denen Sie anrufen sollen retain und release.Meine Allgemeine Faustregel ist, dass, wenn ich wollen zu hängen, um ein Objekt für einige Zeit (wenn es ist eine member-variable in einer Klasse, zum Beispiel), dann muss ich sicherstellen, dass Verweiszähler des Objekts kennt mich.Wie oben beschrieben, ein Objekt Verweiszähler inkrementiert aufrufen retain.Durch die Konvention ist es auch inkrementiert (auf 1 gesetzt, wirklich), wenn das Objekt erstellt wird, das mit einem "init" Methode.In beiden Fällen ist es meine Aufgabe, Anruf release auf das Objekt, wenn ich fertig bin mit ihm.Wenn ich das nicht Tue, wird es einen Speicherverlust.

Beispiel-Objekt erstellen:

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

Jetzt für autorelease.Autorelease ist verwendet als eine praktische (und manchmal notwendig) Weg, zu sagen, das system frei dieses Objekt nach einer Weile.Von einem Sanitär-Perspektive, wenn autorelease heißt, der aktuelle thread ist NSAutoreleasePool alarmiert wird der Anruf.Die NSAutoreleasePool der weiß jetzt, dass, sobald er bekommt die Möglichkeit, sich (nach der aktuellen iteration der Ereignisschleife), es können Anruf release auf das Objekt.Aus unserer Perspektive als Programmierer, es kümmert sich um den Aufruf release für uns, so dass wir nicht haben (und in der Tat, wir sollten nicht zu).

Wichtig zu beachten ist, dass (wieder, durch Konvention) alle Objekt-Erstellung Klasse Methoden geben ein autoreleased Objekt.Zum Beispiel in dem folgenden Beispiel ist die variable "s" hat einen Referenzzähler von 1, aber nach der Ereignis-Schleife abgeschlossen ist, wird es zerstört werden.

NSString* s = [NSString stringWithString:@"Hello World"];

Wenn Sie wollen zu hängen auf string, Sie würde anrufen müssen retain explizit und dann explizit release wenn Sie fertig sind.

Betrachten Sie das folgende (sehr gekünstelt) bit-code, und Sie werden sehen, eine situation, wo 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];
}

Ich merke dies alles etwas verwirrend ist - irgendwann wird es aber auf.Hier sind ein paar Hinweise, um Sie gehen:

  • Apples Einführung Speicher-management.
  • Cocoa-Programmierung für Mac OS X (4th Edition), von Aaron Hillegas - ein sehr gut geschriebenes Buch mit vielen tollen Beispielen.Es liest sich wie ein tutorial.
  • Wenn du wirklich Tauchen in, Sie könnte den Kopf zu Big Nerd Ranch.Dies ist ein training facility run by Aaron Hillegas - der Autor des oben erwähnten Buch.Ich besuchte die Intro Kakao natürlich gibt es vor mehreren Jahren, und es war eine großartige Möglichkeit, um zu lernen.

Andere Tipps

Wenn Sie verstehen, den Prozess von retain/release dann gibt es zwei goldene Regeln, die "duh" offensichtlich etabliert Cocoa-Programmierer, aber leider nur selten geschrieben, das ganz klar für Neulinge.

  1. Wenn Sie eine Funktion, die ein Objekt zurückgibt, hat alloc, create oder copy in seinem Namen dann das Objekt verkaufen.Sie müssen rufen [object release] wenn Sie fertig sind mit es.Oder CFRelease(object), wenn es ein Core-Foundation-Objekt.

  2. Wenn Sie NICHT über eines dieser Wörter, die in seinem Namen dann das Objekt gehört zu jemand anderem.Sie müssen rufen [object retain] wenn Sie möchten, halten Sie das Objekt, nach dem Ende Ihrer Funktion.

Sie wäre gut bedient, auch die Folgen dieser Konvention in Funktionen, die Sie selbst erstellen.

(Nitpicker:Ja, es gibt leider ein paar API-Aufrufe, die Ausnahmen von diesen Regeln, aber Sie sind selten).

Wenn Sie schreiben von code für den desktop und Sie können die Ziel-Mac OS X 10.5, sollten Sie zumindest einen Blick in die mit Objective-C garbage collection.Es ist wirklich vereinfachen Sie die meisten Ihrer Entwicklung, das ist der Grund, warum Apple setzen alle Anstrengungen, um es in die erste Ort, und machen es auch durchführen zu können.

Als Speicher für die management-Regeln, wenn Sie nicht mit GC:

  • Wenn Sie ein neues Objekt erstellen mit +alloc/+allocWithZone:, +new, -copy oder -mutableCopy oder wenn Sie -retain ein Objekt, nehmen Sie Besitz von ihm und müssen sicherstellen, dass Sie gesendet -release.
  • Wenn Sie ein Objekt in irgendeine andere Weise, Sie sind nicht der Besitzer und sollte nicht sicherzustellen, dass es gesendet wird -release.
  • Wenn Sie sicherstellen möchten, dass ein Objekt gesendet wird -release Sie können entweder senden, die sich selbst, oder Sie können senden Sie die Objekt -autorelease und die aktuelle autorelease-pool senden -release (einmal pro erhalten -autorelease), wenn der pool entleert werden.

In der Regel -autorelease wird verwendet, als eine Möglichkeit, um sicherzustellen, dass Objekte, die live für die Länge des aktuellen Ereignisses, aber bereinigt werden, danach, wie es ist ein autorelease-pool umgibt-Kakao-Ereignis-Verarbeitung.In Kakao, es ist weit mehr üblich, die Objekte zurückgeben, um eine Anrufer, die autoreleased als es ist die Rückkehr objets, dass der Anrufer sich lassen muss.

Objective-C verwendet Reference Counting, was bedeutet, dass jedes Objekt einen Referenzzähler.Wenn ein Objekt erstellt wird, hat es eine Referenz Anzahl von "1".Einfach gesagt, wenn ein Objekt bezeichnet wird (dh, die irgendwo gespeichert), es wird "beibehalten", was bedeutet, dass Ihr Referenzzähler um eins erhöht.Wenn ein Objekt nicht mehr benötigt wird, es ist "freigegeben" haben, was bedeutet, dass Ihr Referenzzähler um eins verringert.

Wenn ein Objekt der Referenzzähler 0, wird das Objekt freigegeben wird.Dies ist die grundlegende Referenz zählen.

Für einige Sprachen, Referenzen werden automatisch erhöht und verringert, aber objective-c nicht in einer dieser Sprachen.Damit der Programmierer ist verantwortlich für die Beibehaltung und loslassen.

Eine typische Art und Weise zu schreiben, eine Methode ist:

id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;

Das problem des Müssens zu erinnern, um alle erworbenen Ressourcen innerhalb der code sowohl mühsam und fehleranfällig.Objective-C stellt ein weiteres Konzept darauf abzielt, das viel einfacher:Autorelease-Pools.Autorelease-pools sind spezielle Objekte, die installiert werden für jeden thread.Sie sind ziemlich einfach Klasse, wenn man sich NSAutoreleasePool.

Wenn ein Objekt wird ein "autorelease" - Nachricht gesendet, so wird der Gegenstand look für jeden autorelease-pools sitzen auf dem Stapel für diesen aktuellen thread.Es fügt das Objekt der Liste als ein Objekt zu senden, die "release" - Nachricht, um irgendwann in der Zukunft, die in der Regel, wenn der pool selbst ist freigegeben.

Unter den obigen code, Sie können rewrite es kürzer und einfacher zu Lesen, indem Sie sagen:

id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;

Da das Objekt autoreleased, wir müssen nicht mehr explizit aufrufen "release" auf es.Das ist, weil wir wissen, dass einige autorelease-pool wird es für uns tun später.

Hoffentlich hilft.Der Wikipedia-Artikel ist ziemlich gut über die Referenzzählung.Weitere Informationen über autorelease-pools finden Sie hier.Beachten Sie auch, dass, wenn Sie sind Gebäude, die für Mac OS X 10.5 und höher, man kann sagen, Xcode zu bauen, mit garbage collection aktiviert, so dass Sie, um vollständig zu ignorieren retain/release/autorelease.

Joshua (#6591) - Die Garbage collection Zeug in Mac OS X 10.5 scheint ziemlich cool, aber ist das nicht für das iPhone verfügbar (oder wenn Sie möchten, dass Ihre app für die Ausführung auf pre-10.5 Mac OS X-Versionen).

Auch, wenn Sie schreiben eine Bibliothek oder etwas, das möglicherweise wiederverwendet werden, mit den GC-Modus sperrt jemand mit dem code in auch mit dem GC-Modus, so wie ich es verstehe, jemand versucht zu schreiben, weit wiederverwendbaren code neigt dazu, zu gehen für die Verwaltung von Speicher manuell.

Wie immer, wenn Menschen anfangen, versuchen, wieder zu Wort, die Referenz material Sie fast immer etwas falsch oder bieten eine unvollständige Beschreibung.

Apple bietet eine vollständige Beschreibung der Kakao-Speicher-management-system in Speicher-Management-Programmierhandbuch für Kakao, am Ende gibt es eine kurze, aber genaue Zusammenfassung der Speicher-Management-Regeln.

Ich werde nicht hinzufügen, um die spezifische von retain/release anderen als möchten Sie vielleicht darüber nachdenken, fallen $50 und immer die Hillegass Buch, aber ich würde stark vorschlagen, sich in der Anwendung der Instrumente Werkzeuge sehr früh in der Entwicklung Ihrer Anwendung (sogar das erste!).To do so, Run->Start mit performance-tools.Ich würde anfangen mit Lecks, die ist nur eine von vielen, die verfügbaren Instrumente, sondern Euch helfen werden, wenn Sie vergessen habe, Sie zu entlassen.Es ist quit erschreckend, wie viele Informationen Sie werden vorgestellt mit.Aber schauen Sie sich dieses tutorial aufstehen und gehen schnell:
KAKAO-TUTORIAL:FIXING MEMORY LEAKS MIT INSTRUMENTEN

Tatsächlich versuchen, Kraft Lecks könnten einen besseren Weg, wiederum lernen, wie Sie Sie vermeiden!Viel Glück ;)

Matt Dillard schrieb:

return [[s autorelease] release];

Autorelease tut nicht behalten Sie das Objekt.Autorelease einfach stellt es sich in der Warteschlange freigegeben werden später.Sie wollen nicht zu haben, eine release-Anweisung gibt.

Meine übliche Sammlung von Kakao Speicher-management-Artikel:

Kakao-Speicher-management

Es gibt einen kostenlosen screencast zur Verfügung, aus der iDeveloperTV Netzwerk

Speichermanagement in Objective-C

NilObject die Antwort ist ein guter Anfang.Hier einige Ergänzende info betreffend die manuelle Speicherverwaltung (erforderlich auf dem iPhone).

Wenn Sie sich persönlich alloc/init ein Objekt, es kommt mit einer referenzzahl von 1.Sie sind verantwortlich für die Reinigung nach, wenn es nicht mehr benötigt wird, entweder durch den Aufruf [foo release] oder [foo autorelease].release reinigt es rechts Weg, während autorelease fügt das Objekt auf der autorelease-pool, der wird automatisch release es zu einem späteren Zeitpunkt.

autorelease ist in Erster Linie für Sie, wenn Sie über eine Methode verfügen, muss das Objekt zurückgeben, in Frageso können Sie nicht manuell lösen, sonst wirst du wieder ein null-Objekt), aber Sie wollen nicht zu halten sein, entweder.

Wenn Sie erwerben ein Objekt, in dem Sie nicht nennen alloc/init, um es zu bekommen-zum Beispiel:

foo = [NSString stringWithString:@"hello"];

aber Sie wollen zu hängen, um das Objekt, die Sie benötigen, zu nennen [foo behalten].Ansonsten, es ist möglich, es wird bekommen autoreleased und Sie werden halten auf, um eine nil-Referenz (als wäre es in der oben stringWithString Beispiel).Wenn Sie es nicht mehr benötigen, rufen Sie [foo release].

Die Antworten geben, klare restatement, was die Dokumentation sagt:das problem die meisten neuen Leute laufen ist in der undokumentierten Fälle.Zum Beispiel:

  • Autorelease:docs sagen, es wird trigger eine Freigabe "irgendwann in der Zukunft." WANN?!Grundsätzlich können Sie zählen auf das Objekt herum, bis Sie beenden Sie Ihren code wieder in der system-event-loop.Das system KANN das Objekt freigeben, das jederzeit nach dem aktuellen event-Zyklus.(Ich denke, Matt sagte, dass, früher.)

  • Statische strings: NSString *foo = @"bar"; - hast du behalten oder loslassen, dass die?Nein.Wie wäre

    -(void)getBar {
        return @"bar";
    }
    

    ...

    NSString *foo = [self getBar]; // still no need to retain or release
    
  • Die Schaffung Der Regel:Wenn Sie es erstellt haben, die Sie besitzen, und werden erwartet, um ihn zu lösen.

In Allgemeinen, die Art, new Kakao Programmierer Durcheinander wird, indem Sie nicht verstehen, welche Routinen gibt ein Objekt zurück, mit einer retainCount > 0.

Hier ist ein Ausschnitt aus Sehr Einfache Regeln Für Die Speicherverwaltung In Kakao:

Retention Zählen Regeln

  • Innerhalb eines Blocks, die Verwendung von kopieren, -alloc-und -behalten sollte gleich der Einsatz -release und autorelease.
  • Erstellte Objekte mittels Konstruktoren (z.B.NSString ist stringWithString) sind als autoreleased.
  • Implementieren -dealloc-Methode hinzu, um release die instancevariables Sie selbst

Die 1. Kugel sagt:wenn Sie genannt alloc (oder new fooCopy), müssen Sie rufen Sie release auf das Objekt.

Die 2. Kugel sagt:wenn Sie einem convenience-Konstruktor und Sie müssen das Objekt zu hängen, um (wie bei einem Bild gezeichnet werden später), müssen Sie zu behalten (und dann später release) es.

Die 3. sollten selbsterklärend sein.

Viele gute Informationen auf cocoadev zu:

Wie einige Leute bereits erwähnt, Apple Intro to Memory Management ist bei weitem der beste Ort, um zu starten.

Ein nützlicher link, den ich noch nicht gesehen, noch erwähnt wird Praktische Memory-Management.Finden Sie es in der Mitte des Apple-Dokumente, wenn Sie Sie durchgelesen, aber es lohnt sich die direkte Verknüpfung.Es ist eine brillante Zusammenfassung des memory-management-Regeln, Beispiele und häufige Fehler (im Grunde das, was die anderen Antworten hier sind Sie versuchen zu erklären, aber nicht so gut).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top