weak
Referenzen scheinen in Swift nur zu funktionieren, wenn a protocol
als deklariert ist@objc
, was ich in einer reinen Swift-App nicht möchte.
Dieser Code gibt einen Kompilierungsfehler aus ( weak
kann nicht auf Nicht-Klassentypen angewendet werden MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
Ich muss dem Protokoll ein Präfix voranstellen @objc
, dann funktioniert es.
Frage: Was ist der "reine" schnelle Weg, um eine zu erreichen weak
delegate
?
Antworten:
Sie müssen den Typ des Protokolls als deklarieren
AnyObject
.Wenn
AnyObject
Sie sagen, dass nur Klassen diesem Protokoll entsprechen können, können Strukturen oder Aufzählungen dies nicht.quelle
protocol ProtocolNameDelegate: AnyObject
, spielt aber keine Rolle.AnyObject
daclass
irgendwann veraltet sein.Ergänzende Antwort
Ich war immer verwirrt darüber, ob die Delegierten schwach sein sollten oder nicht. Vor kurzem habe ich mehr über Delegierte und die Verwendung schwacher Referenzen erfahren. Lassen Sie mich hier einige zusätzliche Punkte hinzufügen, um zukünftige Zuschauer zu unterstützen.
Der Zweck der Verwendung des
weak
Schlüsselworts besteht darin, starke Referenzzyklen zu vermeiden (Zyklen beizubehalten). Starke Referenzzyklen treten auf, wenn zwei Klasseninstanzen starke Referenzen zueinander haben. Ihre Referenzzählungen gehen niemals auf Null, sodass sie niemals freigegeben werden.Sie müssen nur verwenden,
weak
wenn der Delegat eine Klasse ist. Schnelle Strukturen und Aufzählungen sind Werttypen (ihre Werte werden kopiert, wenn eine neue Instanz erstellt wird), keine Referenztypen, sodass sie keine starken Referenzzyklen erstellen.weak
Referenzen sind immer optional (andernfalls würden Sie sie verwendenunowned
) und immervar
(nichtlet
), damit die Option auf gesetzt werden kannnil
wenn die Zuordnung aufgehoben wird.Eine übergeordnete Klasse sollte natürlich einen starken Verweis auf ihre untergeordneten Klassen haben und daher das
weak
Schlüsselwort nicht verwenden . Wenn ein Kind jedoch einen Verweis auf seinen Elternteil wünscht, sollte es ihn mithilfe desweak
Schlüsselworts zu einem schwachen Verweis machen .weak
sollte verwendet werden, wenn Sie einen Verweis auf eine Klasse wünschen, die Sie nicht besitzen, nicht nur für ein Kind, das auf sein Elternteil verweist. Wenn zwei nicht hierarchische Klassen aufeinander verweisen müssen, wählen Sie eine, die schwach ist. Welche Sie wählen, hängt von der Situation ab. Weitere Informationen hierzu finden Sie in den Antworten auf diese Frage .In der Regel sollten Delegierte als gekennzeichnet werden,
weak
da die meisten Delegaten auf Klassen verweisen, die sie nicht besitzen. Dies ist definitiv der Fall, wenn ein Kind einen Delegierten verwendet, um mit einem Elternteil zu kommunizieren. In der Dokumentation wird empfohlen, eine schwache Referenz für den Delegaten zu verwenden . (Aber sieh das auch.)Protokolle können für beide verwendet werden Referenztypen (Klassen) und Werttypen (structs, Aufzählungen). In dem wahrscheinlichen Fall, dass Sie einen Delegaten schwach machen müssen, müssen Sie ihn zu einem Nur-Objekt-Protokoll machen. Die Möglichkeit dazu besteht darin
AnyObject
, die Vererbungsliste des Protokolls zu erweitern. (In der Vergangenheit haben Sie dies mit demclass
Schlüsselwort getan ,AnyObject
jetzt wird es jedoch bevorzugt .)Weitere Studie
Das Lesen der folgenden Artikel hat mir geholfen, dies viel besser zu verstehen. Sie diskutieren auch verwandte Themen wie die
unowned
Schlüsselwort und die starken Referenzzyklen, die bei Schließungen auftreten.verbunden
quelle
AnyObject
ist der offizielle Weg, um eine schwache Referenz in Swift zu verwenden.Von Apple:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276
quelle
class
in Swift 4.1 veraltet?Update: Es sieht so aus, als ob das Handbuch aktualisiert wurde und das Beispiel, auf das ich mich bezog, entfernt wurde. Siehe die Bearbeitung der Antwort von @ flainez oben.
Original: Die Verwendung von @objc ist der richtige Weg, auch wenn Sie nicht mit Obj-C zusammenarbeiten. Es stellt sicher, dass Ihr Protokoll auf eine Klasse und nicht auf eine Aufzählung oder Struktur angewendet wird. Siehe "Überprüfen der Protokollkonformität" im Handbuch.
quelle
Das Protokoll muss eine Unterklasse der AnyObject-Klasse sein
Beispiel unten angegeben
quelle
Apple verwendet "NSObjectProtocol" anstelle von "class".
Dies funktioniert auch für mich und hat die Fehler beseitigt, die beim Versuch, mein eigenes Delegatenmuster zu implementieren, aufgetreten sind.
quelle