Gibt es bei Verwendung von Lazy-Initialisierern die Möglichkeit, Retain-Zyklen zu haben?
In einem Blogpost und vielen anderen Orten wird [unowned self]
gesehen
Ich habe das versucht
%Vor%Benutzte es so
%Vor%Und festgestellt, dass "person deinit" wurde protokolliert.
So scheint es, dass es keine Retain-Zyklen gibt. Nach meinem Wissen, wenn ein Block Selbst erfasst und wenn dieser Block stark von Selbst zurückgehalten wird, gibt es einen Retain-Zyklus. Dieser Fall scheint einem Retain-Zyklus ähnlich zu sein, ist es aber nicht.
%Vor%Ich habe das versucht [...]
es scheint, dass es keine Retain-Zyklen gibt
Korrigieren.
Der Grund dafür ist, dass der sofort angewendete Abschluss {}()
als @noescape
gilt. Das erfasste self
wird nicht beibehalten.
Als Referenz: Joe Groffs Tweet .
self
kein Verweis personalizedGreeting
vorhanden ist. Wie MartinR in seinem Kommentar schreibt, können Sie Ihre Hypothese leicht testen, indem Sie protokollieren, ob ein Objekt Person
deinitilt oder nicht, wenn Sie die Aufnahmeliste entfernen.
z. B.
%Vor% Es ist offensichtlich, dass in diesem Fall kein Risiko für einen starken Referenzzyklus besteht und daher die Erfassungsliste von unowned self
im Lazy Closure nicht benötigt wird. Der Grund hierfür ist, dass die verzögerte Schließung nur einmal ausführt und nur den Rückgabewert des Abschlusses verwendet, um personalizedGreeting
(träge) zu instanziieren, während der Verweis auf self
nicht, in In diesem Fall überleben die Ausführung der Schließung.
Wenn wir eine ähnliche Schließung in einer Klasseneigenschaft von Person
speichern würden, würden wir jedoch einen starken Referenzzyklus erstellen, da eine Eigenschaft von self
eine starke Referenz zurück zu self
hätte. Zum Beispiel:
self
als weak
(oder unowned
), standardmäßig Wenn wir das folgende Beispiel betrachten, erkennen wir, dass diese Hypothese falsch ist.
%Vor% I.e., f
in foo()
wird nicht entmineralisiert, und angesichts dieses starken Referenzzyklus können wir die Schlussfolgerung ziehen, dass self
beim instanziierenden Schließen der Lazy-Variablen dummy
stark erfasst wird.
Wir können auch sehen, dass wir nie den starken Referenzzyklus erzeugen, falls wir niemals dummy
instanziieren, was unterstützen würde, dass die fast einmalige faule instantiierende Schließung als Laufzeitbereich betrachtet werden kann (ähnlich wie nie erreicht, wenn) das ist entweder a) nie erreicht (nicht initialisiert) oder b) erreicht, vollständig ausgeführt und "weggeworfen" (Ende des Geltungsbereichs).
Weitere Informationen zu starken Referenzzyklen finden Sie z. B. in
Tags und Links swift lazy-initialization