11

Ich verstehe, dass Sie mit autorelease auf iOS vorsichtig sein müssen. Ich habe eine Methode, die ein Objekt zurückgibt es alloc s, die von dem Aufrufer benötigt wird, so in dieser Situation - wie ich es verstehe - ich muss autorelease an das Objekt im Aufgerufenen senden, bevor es zurückkehrt.Wann bewirkt Autorelease tatsächlich eine Veröffentlichung in Cocoa Touch?

Dies ist in Ordnung, aber sobald die Steuerung zum Telefon zurückkehrt (d. H. Nachdem mein Knopfklick verarbeitet wurde), scheint der Autorelease-Pool freigegeben zu sein. Ich vermute, dass es so ist, wie es sein sollte, aber ich frage mich, was ist die beste Praxis für diese Situation.

Ich habe eine Nachricht retain von dem Aufrufer gesendet, so dass das Objekt nicht freigegeben wird, und es dann explizit in dealloc freigeben.

Ist dies der beste Ansatz?

Antwort

21

Der Autorelease-Pool wird normalerweise nach jeder Iteration der Ausführungsschleife freigegeben. Grob gesagt, ist jeder Cocoa und Cocoa Touch-Anwendung wie folgt strukturiert:

Get the next message out of the queue 
Create an autorelease pool 
Dispatch the message (this is where your application does its work) 
Drain the autorelease pool 

Was Sie beschreiben, ist das erwartete Verhalten. Wenn Sie ein Objekt länger behalten möchten, müssen Sie es explizit beibehalten.

2

Ja, das ist der beste Ansatz. Autorelease ist eigentlich nur für Interaktionen in Code gedacht, den Sie kennen. Sobald Sie ein Objekt gespeichert haben, sollten Sie entweder wissen, dass das Objekt, das eine Referenz enthält, nicht stirbt/den Gültigkeitsbereich verlässt, bis Sie mit dem Objekt fertig sind, oder Sie müssen das Objekt behalten.

1

Es ist nur garantiert, dass automatisch freigegebene Objekte nach dem Ende Ihrer Methode freigegeben werden. Schließlich könnte die Methode, die Ihre Methode aufgerufen hat, einen eigenen Pool erstellt haben und ihn direkt nach Ihrer Methode freigeben.

+0

Streng genommen, auch das ist nicht garantiert, da Sie einen Pool in einem Verfahren schaffen könnten, einige Objekte Autorelease, und lassen Sie das Pool in einem anderen Verfahren. Ein zweifelhaftes Design, aber gültig: Die Objekte werden von der Erstellung des Pools bis zur Entwässerung des Pools reichen, unabhängig von der Methode, mit der der Pool erstellt wurde. –

13

Mit autorelease ist eine Art zu sagen: "Objekt, ich will dich nicht mehr, aber ich werde dich an jemand anderen weitergeben, der dich vielleicht will, also verschwinde noch nicht." Das Objekt bleibt also lange genug stehen, um es von einer Methode zurückzugeben oder einem anderen Objekt zu übergeben. Wenn irgendein Code das Objekt herum behalten möchte, muss er das Eigentumsrecht durch retain in Anspruch nehmen.

Siehe the memory management guidelines für alles, was Sie wissen müssen, um autorelease richtig zu verwenden. Hier

+0

Gute Antwort ABER __ist das sicher__? Gibt es ein Beispiel für eine Zeit, wenn Sie ein Objekt zurückgeben, das Sie [[[Objektzuweisung] init] Autorelease] ', aber dann verschwindet das Objekt, bevor Sie eine Chance hatten, es zu verwenden? – bobobobo

+0

@bobobobo: Nicht, wenn Sie die Speicherverwaltungsregeln befolgen. Das Verhalten von 'autorelease' ist ziemlich vorhersagbar - das Objekt bleibt solange herum, bis der aktuelle Autorelease-Pool leer ist, was bis zum Ende der aktuellen Ereignisschleife nicht passieren wird (es sei denn, Sie machen es absichtlich früher).Wenn Sie z. B. eine Instanzvariable auf das Objekt zeigen, sie aber nicht behalten und dann viel später darauf zugreifen, ist das Objekt verschwunden, bevor Sie es verwenden konnten - aber das liegt daran, dass Sie die Speicherverwaltung durchbrochen haben Vertrag, wenn Sie das Objekt nicht behalten haben. – Chuck

3

ist ein examle in the Apple Memory Management document vorgesehen:

– (id)findMatchingObject:(id)anObject 
{ 
    id match = nil; 
    while (match == nil) { 
     NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init]; 
     /* Do a search that creates a lot of temporary objects. */ 
     match = [self expensiveSearchForObject:anObject]; 
     if (match != nil) { 
      [match retain]; /* Keep match around. */ 
     } 
     [subPool release]; 
    } 
    return [match autorelease]; /* Let match go and return it. */ 
} 
Verwandte Themen