7 Stimmen

Freigabe/Freigabe von zurückgegebenen Objekten

Ich bin neu in Objective-C, also könnte dies eine dumme Frage sein.

Ich kann nicht umhin, die Ähnlichkeiten zwischen ObjC und Microsofts COM in Bezug auf die Speicherverwaltung (AddRef/Release vs. retain/release) zu sehen. In einer COM-Umgebung ist es mehr oder weniger vorgeschrieben, ein Objekt immer zu AddRef (retain) bevor es an den Aufrufer zurückgegeben wird. Soweit ich bisher gesehen habe (ich bin ein Drittel durch Cocoa® Programming for Mac® OS X (3. Auflage)), ist der Teil der Speicherverwaltung etwas unklar.

Angenommen, es gibt kein GC, was ist der idiomatische Weg, um ein Objekt zurückzugeben?

14voto

hamstergene Punkte 23394

Lesen Sie Memory Management Programming Guide über Autorelease-Pools.

In Objective-C sollten Objekte konventionell autoreleased zurückgegeben werden (außer die Methode, die das Objekt zurückgibt, hat einen Namen, der mit "alloc", "new", "copy" oder "mutableCopy" beginnt). Autoreleased Objekte werden von Objective-C in einem Pool verfolgt und automatisch behandelt, was bedeutet, dass Sie sich nicht darum kümmern müssen, ihnen ein endgültiges Release zu senden. Dies vereinfacht die Referenzzählung im Vergleich zu COM erheblich, und deshalb sehen Sie die meisten Zeit keine release-Aufrufe auf zurückgegebenen Objekten. Im Gegensatz dazu legt dieselbe Konvention fest, dass alle Objekte, die von einer Methode zurückgegeben werden, deren Name mit alloc, new, copy oder mutableCopy beginnt, in der Verantwortung des Methodenanrufers liegen. Sie müssen diesen Objekten manuell ein Release aufrufen oder Ihr Programm wird Speicherlecks haben.

0 Stimmen

Fügen Sie nicht blindlings return [objectName autorelease]; am Ende Ihrer Methode hinzu. Bevor Sie das tun, vergewissern Sie sich, dass Sie autorelease nicht an ein Objekt senden, das bereits an anderer Stelle autoreleased wurde, bevor Sie es zurückgeben. Wenn Sie das tun, wird Ihre App wahrscheinlich abstürzen. Zumindest war das meine Erfahrung.

9voto

PeyloW Punkte 36534

Cocoa umgeht die Einschränkungen von AddRef/Release in COM, indem es ein drittes Geschwisterchen einführt: autorelease.

  • retain - Ich brauche das, lass es bestehen.
  • release - Ich brauche das nicht mehr, du kannst es sofort entfernen.
  • autorelease - Ich brauche das nicht, lass es jedoch noch ein paar Sekunden stehen, falls es jemand anderes zuerst abholen möchte.

Durch diese kleine Ergänzung können die meisten Rückgabewerte behandelt werden, als ob wir eine Garbage Collection hätten. Wenn du daran interessiert bist, den Rückgabewert zu behalten, musst du nichts zusätzlich tun.

Um dies zum Funktionieren zu bringen, gibt es eine Konvention (eine Konvention, die gut genug ist, um den Compiler das Speichermanagement automatisch für dich mit der kommenden ARC machen zu lassen):

  • Methoden, die mit diesen müssen zurückgegebene Instanzen beibehalten:
    • alloc
    • copy
    • new
    • retain
  • All andere müssen instanzen mit Autorelease zurückgeben.

Drei Beispelimplementierungen zeigen, wie dies in der Praxis angewendet werden kann:

-(NSString*)newHelloWorldString {
    NSString* s = [NSString stringWithString:@"Hello world"];
    // Apply retain because s in now autoreleased
    return [s retain];
}

-(NSString*)helloWorldString {
    NSString* s = [[NSString alloc] initWithString:@"Hello world"];
    // Apply autorelease because s is now retained.
    return [s autorelease];
}

-(NSString*)fullName {
    // No memory management needed, everything is autoreleased and good.
    NSString* fn = [self firstName];
    NSString* ln = [self lastName];
    NSString* s = [NSString stringWithFormat:@"%@ %@", fn, ln];
    return s;
}

1voto

Devraj Punkte 2985

Allgemein etwas wie

Rückgabe [Objekt freigeben];

und du kannst auf der anderen Seite beibehalten.

Wenn du vorhast, auf Lion/iOS5 bereitzustellen oder das neueste SDK verwendest, schau dir auch ARC an.

0 Stimmen

Ich habe gerade erst angefangen, mit XCode herumzuspielen, und mache das als Hobby, also werde ich in nächster Zeit nichts bereitstellen :D. Was ist ARC, wenn ich fragen darf?

0 Stimmen

Ist das übrigens, wie die Cocoa-Bibliotheken ihre Objekte zurückgeben?

0 Stimmen

ARC = Automatische Referenzzählung. Ein Build-Schritt, der automatisch `retain` und `release` gemäß vereinbarter Muster einfügt.

-1voto

user281300 Punkte 1417

Grundsätzlich würde ich empfehlen, dass die Klasse, die es empfängt, es behält. d.h. die Klasse stackoverflow empfängt das Objekt answer.

d.h.

-(void) setAnswer:(Answer*) _answer{
    self.answer = _answer; // Wenn die Antwort von einer zurückgegebenen Nachricht erstellt wird.
    [_answer release];
}

Bearbeiten: Ich glaube, ich habe jetzt die falschen Dinge da oben stehen. Jetzt, wo ich es mir zum zweiten Mal anschaue. Meinte etwas in der Art:

Answer *_answer = [stackoverflow createAnswer];
self.answer = _answer;
[_answer release];

1 Stimmen

Eine weitere schlechte Antwort XD. Du solltest keine Objekte freigeben, die als Parameter an deine Methode übergeben wurden. Bitte höre auf, Antworten wie diese zu posten, um Anfänger nicht zu verwirren.

0 Stimmen

Bitte erkläre, warum du es hier nicht veröffentlichen kannst, z.B. welche Probleme du dabei haben könntest. Erleuchte mich.

0 Stimmen

Du sollst nur Objekte freigeben, die du selbst erstellt hast. Parameter, die an deine Methode übergeben werden, werden nicht innerhalb deiner Methode erstellt, daher solltest du sie nicht freigeben. Dies führt zu einer "Nachricht gesendet an freigegebene Instanz", wenn der Aufrufer deiner Methode den Parameter freigibt (oder eine Nachricht an ihn sendet).

-3voto

user281300 Punkte 1417

Wenn Sie ein Objekt zurückgeben, liegt es am Besitzer, es zu behalten. Ich würde Autoreleases vermeiden, wo immer möglich, denn sobald der NSPool aktiviert wird, sind diese Objekte verschwunden und können Probleme verursachen, wenn sie immer noch verwendet werden.

Das heißt, Antwort *antwort = [stackoverflow getAnswer] und wenn die Antwort in der getAnswer-Methode erstellt wurde, ist die Person, die sie abruft, dafür verantwortlich, sie freizugeben.

Macht das Sinn?

0 Stimmen

Wie vermeiden Sie das automatische Freigeben eines Objekts, das Sie an Ihren Aufrufer zurückgeben möchten? Rufen Sie [retain] auf und machen Sie den Aufrufer zum Besitzer (obwohl Sie nicht alloc oder new aufgerufen haben)? Oder behalten Sie das Objekt überhaupt nicht bei?

4 Stimmen

Die überwiegende Mehrheit der Methoden sollte ein automatisch freigegebenes Objekt zurückgeben. Der Ratschlag, "Autoreleases nach Möglichkeit zu vermeiden", ist ein schlechter Rat.

0 Stimmen

Ich stehe immer noch zu dem, was ich gesagt habe, vermeide das Zurückgeben von autorelease-Objekten. Dies wurde unzählige Male in den iPhone-Designrichtlinien erwähnt. Wenn Sie beispielsweise etwas aus CoreData zurückgeben, geben Sie nicht einfach ein autorelease-Objekt zurück. Dies bleibt im Speicher, bis der Pool aktiviert wird, und wenn Sie es im Besitzer nicht korrekt beibehalten, treten Speicherprobleme auf, und wenn Sie es dann sind, haben Sie ein autorelease-Objekt, das nichts tut....

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X