In der WWDC 2014-Sitzung 403 Intermediate Swift und im Transkript gab es die folgende Folie
Der Sprecher sagte in diesem Fall, wenn wir es dort nicht verwenden [unowned self]
, wird es ein Speicherverlust sein. Bedeutet das, dass wir immer einen [unowned self]
Innenverschluss verwenden sollten?
In Zeile 64 von ViewController.swift der Swift Weather-App verwende ich nicht [unowned self]
. Aber ich aktualisiere die Benutzeroberfläche mit einigen @IBOutlet
s wie self.temperature
und self.loadingIndicator
. Es kann in Ordnung sein, weil alle von @IBOutlet
mir definierten s sind weak
. Aber sollten wir aus Sicherheitsgründen immer verwenden [unowned self]
?
class TempNotifier {
var onChange: (Int) -> Void = {_ in }
var currentTemp = 72
init() {
onChange = { [unowned self] temp in
self.currentTemp = temp
}
}
}
swift
automatic-ref-counting
Jake Lin
quelle
quelle
onChange
sollte ein[weak self]
Abschluss sein, da es sich um eine öffentliche (interne, aber immer noch) Eigenschaft handelt, sodass ein anderes Objekt den Abschluss abrufen und speichern kann, wobei das TempNotifier-Objekt erhalten bleibt (unbegrenzt, wenn Das benutzende Objekt ließ denonChange
Verschluss nicht los, bis es sieht, dass dasTempNotifier
weg ist, über seinen eigenen schwachen Verweis auf dasTempNotifier
) . Wennvar onChange …
warenprivate var onChange …
dann[unowned self]
wäre richtig. Ich bin mir dessen jedoch nicht 100% sicher. jemand korrigiert mich bitte, wenn ich falsch liege.[]
? Ich kann die Erklärung nicht in den Apple-Dokumenten finden.{}
ist der leere Abschluss (die Instanz des Abschlusses) als Standard (macht nichts),(Int) -> Void
ist die Abschlussdefinition.Antworten:
Nein, es gibt definitiv Zeiten, in denen Sie nicht verwenden möchten
[unowned self]
. Manchmal möchten Sie, dass der Verschluss sich selbst erfasst, um sicherzustellen, dass er zum Zeitpunkt des Aufrufs des Verschlusses noch vorhanden ist.Beispiel: Erstellen einer asynchronen Netzwerkanforderung
Wenn Sie eine asynchrone Netzwerkanfrage machen Sie tun wollen , dass der Verschluss zu halten
self
für , wenn die Anforderung abgeschlossen ist . Dieses Objekt wurde möglicherweise anderweitig freigegeben, Sie möchten jedoch weiterhin in der Lage sein, die Anforderung zu bearbeiten.Wann
unowned self
oder verwendenweak self
Das einzige Mal, wo Sie wirklich verwenden möchten
[unowned self]
oder sind,[weak self]
ist, wenn Sie einen starken Referenzzyklus erstellen würden . Ein starker Referenzzyklus liegt vor, wenn es eine Eigentumsschleife gibt, in der sich Objekte gegenseitig besitzen (möglicherweise durch Dritte) und daher niemals freigegeben werden, da beide sicherstellen, dass sie sich gegenseitig halten.Im speziellen Fall eines Abschlusses müssen Sie nur erkennen, dass jede Variable, auf die darin verwiesen wird, dem Abschluss "gehört". Solange der Verschluss vorhanden ist, sind diese Objekte garantiert vorhanden. Die einzige Möglichkeit, dieses Eigentum zu stoppen, besteht darin, das
[unowned self]
oder zu tun[weak self]
. Wenn also eine Klasse einen Abschluss besitzt und dieser Abschluss einen starken Verweis auf diese Klasse erfasst, haben Sie einen starken Referenzzyklus zwischen dem Abschluss und der Klasse. Dies schließt auch ein, ob die Klasse etwas besitzt, das den Abschluss besitzt.Speziell im Beispiel aus dem Video
In dem Beispiel auf der Folie
TempNotifier
besitzt der Abschluss über dieonChange
Elementvariable. Wenn sie nicht erklären haben ,self
wieunowned
würde die Schließung auch selbstself
einen starken Referenzzyklus zu schaffen.Unterschied zwischen
unowned
undweak
Der Unterschied zwischen
unowned
undweak
besteht darin, dass diesweak
als optional deklariert wird, während diesunowned
nicht der Fall ist. Wenn Sie es deklarieren, könnenweak
Sie den Fall behandeln, dass es irgendwann im Verschluss Null sein könnte. Wenn Sie versuchen, auf eineunowned
Variable zuzugreifen , die zufällig Null ist, stürzt das gesamte Programm ab. Verwendenunowned
Sie diese Variable also nur, wenn Sie sicher sind, dass sie immer verfügbar ist, während der Abschluss vorhanden istquelle
[weak self]
in einer asynchronen Netzwerkanforderung befindet sich in einem Ansichtscontroller, in dem diese Anforderung zum Auffüllen der Ansicht verwendet wird. Wenn der Benutzer zurücktritt, müssen wir die Ansicht nicht mehr füllen und benötigen auch keinen Verweis auf den Ansichts-Controller.weak
Verweise werden auch auf gesetzt,nil
wenn die Zuordnung des Objekts aufgehoben wird.unowned
Referenzen sind nicht.unowned
wird verwendet,non-Optional
während verwendetweak
wird,Optional
damit unserself
istOptional
odernon-optional
?Update 11/2016
Ich habe einen Artikel darüber geschrieben, in dem diese Antwort erweitert wurde (ich habe in SIL nachgesehen, um zu verstehen, was ARC tut). Lesen Sie ihn hier .
Ursprüngliche Antwort
Die vorherigen Antworten geben nicht wirklich einfache Regeln darüber, wann und warum sie übereinander verwendet werden sollen. Lassen Sie mich daher einige Dinge hinzufügen.
Die nicht besessene oder schwache Diskussion läuft auf eine Frage der Lebensdauer der Variablen und des Verschlusses hinaus, der darauf verweist.
Szenarien
Sie können zwei mögliche Szenarien haben:
Der Verschluss hat die gleiche Lebensdauer der Variablen, sodass der Verschluss nur erreichbar ist , bis die Variable erreichbar ist . Die Variable und der Verschluss haben die gleiche Lebensdauer. In diesem Fall sollten Sie die Referenz als nicht besessen deklarieren . Ein häufiges Beispiel ist das
[unowned self]
in vielen Beispielen verwendete Beispiel für kleine Verschlüsse, die etwas im Kontext ihrer Eltern tun und auf die nirgendwo anders verwiesen wird, die ihre Eltern nicht überleben.Die Verschlusslebensdauer ist unabhängig von der der Variablen. Auf den Verschluss kann immer noch verwiesen werden, wenn die Variable nicht mehr erreichbar ist. In diesem Fall sollten Sie die Referenz als schwach deklarieren und sicherstellen, dass sie nicht Null ist, bevor Sie sie verwenden (erzwingen Sie nicht das Auspacken). Ein häufiges Beispiel hierfür ist das Beispiel, das
[weak delegate]
Sie in einigen Beispielen für das Schließen eines völlig unabhängigen (lebenslangen) Delegatenobjekts sehen können.Tatsächliche Verwendung
Also, welche werden / sollten Sie eigentlich die meiste Zeit verwenden?
Zitat von Joe Groff von Twitter :
Sie werden mehr über unowned finden
*
Innenleben hier .*
Wird normalerweise auch als nicht besessen (sicher) bezeichnet, um anzuzeigen, dass Laufzeitprüfungen (die zu einem Absturz auf ungültige Referenzen führen) durchgeführt werden, bevor auf die nicht besessene Referenz zugegriffen wird.quelle
Ich dachte, ich würde einige konkrete Beispiele speziell für einen View Controller hinzufügen. Viele der Erklärungen, nicht nur hier zu Stack Overflow, sind wirklich gut, aber ich arbeite besser mit Beispielen aus der Praxis (@drewag hatte einen guten Anfang damit):
weak
, da sie langlebig sind. Der Ansichtscontroller kann geschlossen werden, bevor die Anforderung abgeschlossen ist, sodassself
beim Aufruf des Abschlusses nicht mehr auf ein gültiges Objekt verweist.Wenn Sie einen Abschluss haben, der ein Ereignis auf einer Schaltfläche behandelt. Dies kann daran liegen
unowned
, dass die Schaltfläche und alle anderen Elemente, auf die verwiesen wird, gleichzeitig verschwinden, sobald der Ansichts-Controller ausgeblendetself
wird. Gleichzeitig verschwindet auch der Verschlussblock.quelle
weak
eher verwenden alsunowned
richtig?Wenn das Selbst im Verschluss gleich Null sein könnte, benutze [schwaches Selbst] .
Wenn das Selbst im Verschluss niemals Null sein wird, verwenden Sie [nicht besessenes Selbst] .
Die Apple Swift-Dokumentation enthält einen großartigen Abschnitt mit Bildern, in denen der Unterschied zwischen der Verwendung von starken , schwachen und nicht besessenen Verschlüssen erläutert wird :
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
quelle
Hier sind brillante Zitate aus Apple Developer Forums, die köstliche Details beschreiben:
unowned
vsunowned(safe)
vsunowned(unsafe)
unowned
vs.weak
Update: In der modernen Swift
weak
intern verwendet den gleichen Mechanismus wieunowned
tut . Dieser Vergleich ist also falsch, weil er Objective-Cweak
mit Swift vergleichtunonwed
.Gründe dafür
Aufgeregt, was?
quelle
Hier gibt es einige gute Antworten. Die jüngsten Änderungen an der Implementierung schwacher Referenzen durch Swift sollten jedoch die schwachen Selbst- und Nicht-Eigennutzungsentscheidungen aller ändern. Wenn Sie zuvor die beste Leistung mit nicht besessenem Selbst benötigten, war dies dem schwachen Selbst überlegen, solange Sie sicher sein konnten, dass das Selbst niemals Null sein würde, da der Zugriff auf das nicht besessene Selbst viel schneller ist als der Zugriff auf das schwache Selbst.
Mike Ash hat jedoch dokumentiert, wie Swift die Implementierung schwacher Vars aktualisiert hat, um Beistelltische zu verwenden, und wie dies die schwache Selbstleistung erheblich verbessert.
https://mikeash.com/pyblog/friday-qa-2017-09-22-swift-4-weak-references.html
Jetzt, da es keine signifikanten Leistungseinbußen für das schwache Selbst gibt, sollten wir es meiner Meinung nach künftig standardmäßig verwenden. Der Vorteil des schwachen Selbst ist, dass es optional ist, was es viel einfacher macht, korrekteren Code zu schreiben. Dies ist im Grunde der Grund, warum Swift eine so großartige Sprache ist. Sie denken vielleicht, Sie wissen, welche Situationen für die Verwendung von nicht besessenem Selbst sicher sind, aber meine Erfahrung beim Überprüfen vieler anderer Entwicklercodes ist, dass die meisten dies nicht tun. Ich habe viele Abstürze behoben, bei denen nicht freigegebenes Selbst freigegeben wurde, normalerweise in Situationen, in denen ein Hintergrund-Thread abgeschlossen wird, nachdem ein Controller freigegeben wurde.
Fehler und Abstürze sind die zeitaufwändigsten, schmerzhaftesten und teuersten Teile der Programmierung. Geben Sie Ihr Bestes, um den richtigen Code zu schreiben und ihn zu vermeiden. Ich empfehle, es zur Regel zu machen, niemals Auspackoptionen zu erzwingen und niemals ein nicht besessenes Selbst anstelle eines schwachen Selbst zu verwenden. Sie werden nichts verlieren, wenn Sie die Zeiten verpassen, in denen das Auspacken erzwungen wird und das nicht besessene Selbst tatsächlich sicher ist. Aber Sie werden viel davon profitieren, wenn Sie schwer zu findende Abstürze und Fehler beseitigen und Fehler beheben.
quelle
weak
nicht anstelle einer verwendet werden kannunowned
?Laut Apple-Doc
Beispiel -
quelle
Wenn keiner der oben genannten Punkte Sinn macht:
tl; dr
Erläuterung:
Ich habe Folgendes unter folgender Adresse abgerufen: schwacher, nicht besessener Link . Nach allem, was ich gesammelt habe, kann nicht besessenes Selbst nicht Null sein, aber schwaches Selbst kann es sein, und nicht besessenes Selbst kann zu baumelnden Zeigern führen ... etwas, das in Objective-C berüchtigt ist. Ich hoffe es hilft
Nicht besessene Referenzen erhöhen wie schwache Referenzen nicht die Anzahl der Aufbewahrungen des Objekts, auf das verwiesen wird. In Swift hat eine nicht im Besitz befindliche Referenz jedoch den zusätzlichen Vorteil, dass sie nicht optional ist . Dies erleichtert die Verwaltung, anstatt die optionale Bindung zu verwenden. Dies ist nicht anders als implizit nicht verpackte Optionen. Darüber hinaus sind nicht besessene Referenzen nicht Null . Dies bedeutet, dass beim Freigeben des Objekts der Zeiger nicht auf Null gesetzt wird. Dies bedeutet, dass die Verwendung nicht besessener Referenzen in einigen Fällen zu baumelnden Zeigern führen kann. Für Sie Nerds da draußen, die sich wie ich an die Objective-C-Tage erinnern, werden nicht besessene Referenzen unsicheren_unretained Referenzen zugeordnet.
Hier wird es etwas verwirrend.
Sie können beide verwendet werden, um Haltezyklen zu unterbrechen. Wann verwenden wir sie?!
Laut Apples Dokumenten :
quelle
quelle