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];
}
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.
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.
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 .
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.
Ich fand, dass dieser Link die beste Erklärung gab, wann und wie NSAutoReleasePool verwendet wird: AutoReleasePool
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.
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
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."