Warum ist @autoreleasepool Bedarf noch mit ARC?
Zum größten Teil mit ARC (Automatic Reference Counting), die wir nicht brauchen, zu denken, über memory-management mit Objective-C-Objekte. Es ist nicht gestattet, erstellen Sie NSAutoreleasePool
s mehr, jedoch gibt es eine neue syntax:
@autoreleasepool {
…
}
Meine Frage ist, warum würde ich jemals brauchen, wenn ich nicht beauftragt bin, werden manuell freigeben/autoreleasing ?
EDIT: Um zusammenzufassen, was ich aus all den anwers und Kommentare kurz und bündig:
Neue Syntax:
@autoreleasepool { … }
neue syntax für
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
…
[pool drain];
Noch wichtiger ist:
- ARC verwendet
autorelease
sowierelease
. - Braucht es eine auto-release-pool im Ort, dies zu tun.
- ARC nicht erstellen Sie die auto-release-pool für Sie. Jedoch:
- Der Haupt-thread eines jeden Cocoa-app hat bereits einen autorelease pool.
- Es gibt zwei Gelegenheiten, bei denen Sie vielleicht nutzen möchten
@autoreleasepool
:- Wenn Sie in einem sekundären thread und es gibt keine auto-release-pool, Sie müssen Ihre eigenen zu verhindern, dass Leckagen, wie
myRunLoop(…) { @autoreleasepool { … } return success; }
. - Wenn Sie möchten, um einen lokalen pool, da @mattjgalloway gezeigt hat in seiner Antwort.
- Wenn Sie in einem sekundären thread und es gibt keine auto-release-pool, Sie müssen Ihre eigenen zu verhindern, dass Leckagen, wie
InformationsquelleAutor der Frage mk12 | 2012-01-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
ARC nicht loszuwerden behält, releases und autoreleases, es fügt nur in die benötigte Fotos für Sie. So gibt es immer noch Anrufe zu erhalten, gibt es immer noch Anrufe zum release gibt es noch immer fordert, autorelease und es gibt immer noch auto release pools.
Einer der anderen machten Sie mit der neuen Clang 3.0-compiler und ARC ist, dass Sie ersetzt
NSAutoReleasePool
mit der@autoreleasepool
compiler-Direktive.NSAutoReleasePool
war immer ein bisschen ein besonderes "Objekt" wie auch immer, und Sie machten es so, dass die syntax des mit ein ist nicht zu verwechseln mit einem Objekt, so dass es in der Regel ein bisschen einfacher.Also im Grunde, müssen Sie
@autoreleasepool
denn es gibt immer noch auto release pools zu kümmern. Sie nur brauchen nicht zu sorgen über das hinzufügen inautorelease
Anrufe.Ein Beispiel der Verwendung einer auto-release-pool:
Enorm erfundenes Beispiel, sicher, aber wenn Sie nicht über die
@autoreleasepool
innerhalb der äußerenfor
-Schleife, dann würde die Freigabe 100000000 Objekte später auf, anstatt 10000 jede Runde, die äußerefor
-Schleife.Update:
Siehe auch diese Antwort - https://stackoverflow.com/a/7950636/1068248 - warum
@autoreleasepool
ist nichts mit ARC.Update:
Ich warf einen Blick in das innere, was hier Los ist und schrieb es auf meinem blog. Wenn Sie einen Blick nehmen, dann sehen Sie genau, was ARC ist und wie der neue Stil
@autoreleasepool
und wie es wird ein Bereich verwendet, der vom compiler zu schließen, Informationen über das, was behält, releases & autoreleases erforderlich sind.InformationsquelleAutor der Antwort mattjgalloway
@autoreleasepool
nicht autorelease nichts. Es schafft einen autorelease-pool, sodass, wenn das Ende des Blocks erreicht ist, werden alle Objekte wurden autoreleased von BOGEN, während der Baustein aktiv war, wird gesendet release-Nachrichten. Apple Advanced Memory Management Programming Guide erklärt es so:InformationsquelleAutor der Antwort outis
Menschen oft missverstehen ARC für eine Art von garbage collection oder ähnliches. Die Wahrheit ist, dass nach einiger Zeit Leute bei Apple (Dank llvm und clang-Projekte) realisiert, die in Objective-C, s-Speicher-Verwaltung (alle
retains
undreleases
usw.) können voll automatisiert am compile-Zeit. Dies ist nur durch das Lesen der code, noch bevor es ausgeführt wird! 🙂Um so zu tun es gibt nur eine Bedingung: Wir MÜSSEN den Regelnsonst würde der compiler nicht in der Lage sein, um den Prozess zu automatisieren zur compile-Zeit. So,, um sicherzustellen, dass wir nie die Regeln zu brechen, dürfen wir nicht explizit schreiben
release
retain
usw. Diese Anrufe werden Automatisch injiziert in unsere Codes durch den compiler. Also intern haben wir nochautorelease
sretain
release
usw. Es ist nur, wir brauchen nicht zu schreiben, Sie nicht mehr.Den Ein ARC ist automatisch bei der Kompilierung, die ist viel besser als zur Laufzeit wie die garbage-collection.
Wir haben noch
@autoreleasepool{...}
da es nicht zu brechen alle Regeln, die wir kostenlos erstellen/drain-unser pool jederzeit wir es brauchen :).InformationsquelleAutor der Antwort nacho4d
Es ist, weil Sie noch brauchen, um dem compiler mit Hinweise dazu, Wann es sicher ist, für autoreleased-Objekte den Gültigkeitsbereich verlässt.
InformationsquelleAutor der Antwort DougW
Zitiert aus https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html:
...
InformationsquelleAutor der Antwort Raunak
Autorelease pools sind erforderlich für die Rücksendung neu erstellte Objekte aus einer Methode. E. g. betrachten Sie dieses Stück code:
Den string erstellt in der Methode wird eine retain-count ein. Nun, wer soll das Gleichgewicht behalten, dass rechnen mit einem release?
Die Methode selbst? Nicht möglich, es muss return das erzeugte Objekt, also muss es nicht loslassen, es vor der Rückgabe.
Den Aufrufer der Methode? Der Anrufer ist nicht zu erwarten, um ein Objekt, dass eine Freigabe erforderlich ist, der name der Methode impliziert nicht, dass ein neues Objekt erstellt wird, es sagt nur, dass ein Objekt zurückgegeben wird und das zurückgegebene Objekt kann eine neue sein die eine Freigabe, aber es kann auch sein, ein vorhandenes, nicht. Was die Methode keine Rückgabe kann auch davon abhängen, einige internen Zustand, so das der Anrufer nicht wissen, ob es zu release, das Objekt und es sollte nicht zu kümmern.
Wenn der Anrufer hatte immer die Freilassung aller zurückgegebenen Objekt durch Konvention, dann jedes Objekt nicht neu erstellt würde immer beibehalten werden müssen, vor der Rückgabe von einer Methode, und es müsste vom Aufrufer freigegeben werden, sobald es geht out of scope, es sei denn, es wird wieder. Das wäre höchst ineffizient, in vielen Fällen kann man vollständig vermeiden, verändern, behalten zählt in vielen Fällen, wenn der Anrufer wird nicht immer lassen Sie die zurückgegebene Objekt.
Deshalb gibt es autorelease-pools, also die erste Methode wird in der Tat geworden
Aufrufen
autorelease
auf ein Objekt und fügt es an den autorelease-pool, aber was bedeutet dies wirklich, hinzufügen ein Objekt in den autorelease-pool? Nun, es bedeutet zu sagen, Ihr system "ich möchte, dass Sie zum release das Objekt für mich, aber einige Zeit später, nicht jetzt; es hat einen retain count, muss ausgeglichen werden durch ein release-ansonsten Speicher undicht werden, aber das kann ich nicht, dass ich mich jetzt, wie muss ich das Objekt am Leben zu bleiben und über meine aktuellen Bereich und meine Anrufer nicht tun, wird es für mich entweder, es hat keine Kenntnis, dass dies getan werden muss. So fügen Sie es zu Ihrem pool und sobald Sie säubern den pool, auch sauber bis mein Objekt für mich."Mit ARC-der compiler entscheidet für Sie, wenn die Beauftragung eines Objekts, wenn ein Objekt loslassen und, wenn um Sie ein autorelease pool, aber es erfordert noch die Anwesenheit des autorelease-pools zurückkehren zu können neu erstellte Objekte aus Methoden ohne Speicherlecks. Apple hat soeben einige nette Optimierungen der generierte code wird manchmal beseitigen autorelease-pools während der Laufzeit. Diese Optimierungen erfordern, dass beide, der Anrufer und der angerufene sind mit ARC (erinnern mischen ARC und nicht-ARC ist legal und auch offiziell unterstützt) und wenn das tatsächlich der Fall ist, kann nur zur Laufzeit bekannt.
Betrachten Sie diese ARC-Code:
Den code, den das system erzeugt, kann entweder Verhalten sich wie in der folgenden code (das ist die sichere version, die Ihnen erlaubt frei zu mischen ARC und nicht-ARC-code):
(Beachten Sie die retain/release in der Anrufer ist nur eine defensive Sicherheit behalten, ist es nicht unbedingt erforderlich, würde der code vollkommen korrekt, ohne es)
Oder kann es sich Verhalten, wie dieser code, im Fall, dass beide erkannt werden, verwenden Sie einen BOGEN an Laufzeit:
Wie Sie sehen können, Apple beseitigt die atuorelease, damit auch das verzögerte Objekt freigeben, wenn der pool ist zerstört, ebenso wie die Sicherheit behalten. Erfahren Sie mehr darüber, wie das möglich ist und was wirklich passiert hinter den kulissen, schauen Sie sich dieses blog-post.
Nun zu der eigentlichen Frage: Warum sollte man verwenden
@autoreleasepool
?Für die meisten Entwickler, es gibt nur einen Grund, warum die linke heute für die Verwendung dieses Konstrukt in Ihren code, und das ist zu halten, der Speicher-footprint klein, wo anwendbar. E. g. betrachten Sie diese Schleife:
Davon ausgehen, dass jeder Aufruf
tempObjectForData
können erstellen Sie eine neueTempObject
zurückgegeben wird autorelease. Die for-Schleife erstellen, die eine million von diesen temp-Objekte, die alle gesammelt in der aktuellen autoreleasepool, und nur einmal, der pool ist zerstört, alle temp-Objekte sind ebenso zerstört. Bis das geschieht, haben Sie eine million von diesen temp-Objekte im Speicher.Wenn Sie schreiben Sie den code wie folgt statt:
Dann einen neuen pool erstellt jedes mal die for-Schleife läuft und zerstört am Ende jeder loop-iteration. So bei den meisten ein temp-Objekt ist hängend um im Speicher zu jeder Zeit trotz der Schleife läuft eine Millionen mal.
In der Vergangenheit hatten Sie oft auch zu handhaben autoreleasepools sich bei der Verwaltung der threads (z.B. mit
NSThread
), da nur der main-thread hat automatisch einen autorelease-pool für Cocoa/UIKit app. Doch das ist so ziemlich Vermächtnis heute als heute würden Sie wahrscheinlich nicht verwenden threads, um mit zu beginnen. Sie verwenden würde, GCDDispatchQueue
's oderNSOperationQueue
's und diese beiden machen die Verwaltung einer top-level-autorelease-pool für Sie, erstellt, bevor Sie einen block/Aufgabe und zerstört einmal mit ihm getan.InformationsquelleAutor der Antwort Mecki
Es scheint eine Menge Verwirrung zu diesem Thema (und mindestens 80 Menschen, die wahrscheinlich sind jetzt verwirrt über diese und denken, Sie brauchen zu streuen @autoreleasepool um Ihren code).
Wenn ein Projekt (inklusive seiner Abhängigkeiten) setzt ausschließlich auf ARC, dann @autoreleasepool muss nie verwendet werden, und tun nichts sinnvolles. ARC handle freigeben von Objekten in der richtigen Zeit. Zum Beispiel:
zeigt:
Jedes Test-Objekt freigegeben wird, sobald der Wert außerhalb des Gültigkeitsbereichs, ohne zu warten, für einen autorelease pool zu verlassen. (Das gleiche passiert mit der NSNumber Beispiel nur lässt uns beobachten, die dealloc.) ARC nicht verwenden autorelease.
Den Grund @autoreleasepool ist immer noch erlaubt ist, ist für den gemischten ARC und nicht-ARC-Projekte, die noch nicht vollständig umgestellt, um ARC.
Wenn Sie einen Anruf in non-ARC code es zurück einen autoreleased-Objekt. In diesem Fall, die obige Schleife würde Auslaufen, da der aktuelle autorelease pool wird nie verlassen. Das ist, wo Sie wollen, setzen Sie ein @autoreleasepool, um den code-block.
Aber wenn Sie schon komplett aus der ARC-übergang, dann vergessen Sie autoreleasepool.
InformationsquelleAutor der Antwort Glenn Maynard