it-swarm-eu.dev

Wie funktioniert der Autorelease-Pool von NSAutoreleasePool?

Soweit ich es verstehe, muss alles, was mit einer alloc , new oder copy erstellt wurde, manuell freigegeben werden. Zum Beispiel:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

Meine Frage ist jedoch, ob dies nicht genauso gültig wäre:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}
94
James Sumners

Ja, Ihr zweiter Code-Snippit ist vollkommen gültig.

Jedes Mal, wenn -autorelease an ein Objekt gesendet wird, wird es dem innersten Autorelease-Pool hinzugefügt. Wenn der Pool leer ist, sendet er einfach die Freigabe an alle Objekte im Pool.

Autorelease-Pools sind einfach eine Annehmlichkeit, mit der Sie das Senden von Sendungen auf "später" verschieben können. Das "spätere" kann an verschiedenen Stellen passieren, aber die häufigste Anwendung in Cocoa-GUI-Apps ist das Ende des aktuellen Laufschleifenzyklus.

65
kperryua

NSAutoreleasePool: Drain vs. Release

Da die Funktion von drain und release für Verwirrung zu sorgen scheint, kann es angebracht sein, hier zu klären (obwohl dies in der Dokumentation ... beschrieben wird).

Genau genommen ist drain aus der Perspektive des großen Bildes nicht äquivalent zu release:

In einer Umgebung mit Referenzzählung führt drain die gleichen Operationen wie release aus, sodass die beiden in diesem Sinne gleichwertig sind. Um dies zu betonen, bedeutet dies, dass Sie nicht einen Pool durchlaufen, wenn Sie drain anstelle von release verwenden.

In einer Müllsammelumgebung ist release ein No-Op. Es hat also keine Wirkung. drain enthält dagegen einen Hinweis an den Collector, dass er "bei Bedarf sammeln" sollte. In einer Umgebung, in der Müll gesammelt wird, hilft die Verwendung von drain dabei, dass das System die Sammlung von Gleichgewichten durchführt.

37
mmalc

Wie bereits erwähnt, ist Ihr zweites Code-Snippet korrekt.

Ich möchte eine kürzere Methode für die Verwendung des Autorelease-Pools vorschlagen, der in allen Umgebungen funktioniert (Referenzzählung, GC, ARC) und auch die Verwirrung zwischen Drain und Release vermeidet:

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

Beachten Sie im obigen Beispiel den Block @autoreleasepool. Dies ist dokumentiert hier .

17
Neovibrant

Nein, du liegst falsch. Aus der Dokumentation geht eindeutig hervor, dass -drain unter non-GC -release gleichbedeutend mit -release ist, dh der NSAutoreleasePool wird nicht durchgesickert.

7
kperryua

Ich fand, dass dieser Link die beste Erklärung gab, wann und wie NSAutoReleasePool verwendet wird: AutoReleasePool

1
Wayne Lo

durch das Senden einer automatischen Freigabe anstelle einer Freigabe an ein Objekt wird die Lebensdauer dieses Objekts mindestens verlängert, bis der Pool selbst leer ist (es kann länger sein, wenn das Objekt anschließend beibehalten wird). Ein Objekt kann mehrmals in demselben Pool abgelegt werden. In diesem Fall erhält es eine Freigabemeldung für jedes Mal, wenn es in den Pool aufgenommen wurde.

0
Hardik Mamtora

ja, Ihr Code ist perfekt. Wenn Sie Müllsammlung verwenden, reicht es aus, die Zeichenfolge auf Null zu setzen, wenn Sie damit fertig sind. Das Sammeln von Müll ist nicht gut für die Leistung Ihrer App, daher würde ich die Verwendung nicht empfehlen: P

0

Was ich von Apple gelesen habe: "Am Ende des Blockes für den Autorelease-Pool werden Objekten, die eine Autorelease-Nachricht erhalten haben, eine Freigabemeldung gesendet. Ein Objekt erhält eine Freigabemeldung für jedes Mal, wenn eine Autorelease-Nachricht gesendet wurde der Block."

https://developer.Apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

0
Gagan_iOS