Schwache Protokollreferenzen in Swift ohne @objc: Vollständige Anleitung

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Wie erstelle ich eine schwache Referenz auf ein Protokoll in reinem Swift (ohne @objc)? Vollständige Anleitung mit Beispielen

\n\n

Stellen Sie sich vor: Sie schreiben eine App in Swift, verwenden das Delegate-Muster, und plötzlich – bumm! – Ihre Objekte werden nicht freigegeben, der Speicher wächst und die App wird langsamer. Kommt Ihnen das bekannt vor? Höchstwahrscheinlich sind Sie auf einen Retain Cycle (Zyklus starker Referenzen) gestoßen. Ein klassisches Problem, bei dem der Delegierte eine starke Referenz auf den Besitzer hält und der Besitzer eine starke Referenz auf den Delegierten. Die erste Lösung, die einem in den Sinn kommt, ist, die Referenz auf das Protokoll schwach (weak) zu machen. Aber hier überrascht Swift: Sie können nicht einfach weak var delegate: MyProtocol deklarieren, wenn das Protokoll nicht mit @objc markiert ist. Der Compiler gibt einen Fehler aus. Warum? Und vor allem – wie umgeht man das?

\n\n

In diesem Artikel werden wir besprechen, wie man eine schwache Protokollreferenz in reinem Swift ohne @objc erstellt. Sie erfahren, warum dies überhaupt ein Problem ist, welche Lösungen es gibt und wie Sie sauberen, sicheren Code ohne Speicherlecks schreiben. Los geht's!

\n\n

Warum funktioniert eine schwache Protokollreferenz nicht „von Haus aus"?

\n\n

Erinnern wir uns, wie weak in Swift funktioniert. Eine schwache Referenz (weak) kann nur für Reference Types (Klassen) existieren. Warum? Weil nur Objekte von Klassen die Speicherverwaltung über ARC (Automatic Reference Counting) haben. Strukturen (struct) und Aufzählungen (enum) sind Value Types, sie werden kopiert, und das Konzept einer „schwachen Referenz" ergibt für sie keinen Sinn.

\n\n

Wenn Sie schreiben:

\n
weak var delegate: MyProtocol?
\n

Weiß der Compiler nicht, ob MyProtocol von einer Klasse, einer Struktur oder einer Aufzählung implementiert wird. Was, wenn es eine Struktur ist? Dann kann weak nicht angewendet werden. Daher der Fehler: „'weak' may only be applied to class and class-bound protocol types".

\n\n

Früher (in Objective-C) konnten alle Protokolle standardmäßig nur von Klassen implementiert werden, daher funktionierte weak. In reinem Swift sind Protokolle universell – das ist großartig, fügt aber Komplexität hinzu.

\n\n

Lösung Nr. 1: Class-bound Protocol (auf Klassen beschränktes Protokoll)

\n\n

Der einfachste und gebräuchlichste Weg ist, explizit anzugeben, dass das Protokoll nur von Klassen implementiert werden kann. Dazu wird das Schlüsselwort AnyObject (oder das veraltete class) in der Protokoll-Deklaration verwendet.

\n\n

Beispiel:

\n
protocol MyDelegate: AnyObject {\n    func didSomething()\n}\n\nclass ViewController {\n    weak var delegate: MyDelegate?\n\n    func doSomething() {\n        delegate?.didSomething()\n    }\n}\n\nclass SomeClass: MyDelegate {\n    func didSomething() {\n        print("Delegat ausgelöst!")\n    }\n}\n\n// Verwendung\nlet vc = ViewController()\nlet some = SomeClass()\nvc.delegate = some\nvc.doSomething() // Gibt aus: "Delegat ausgelöst!"
\n\n

Alles funktioniert. MyDelegate kann jetzt nur von einer Klasse (class) implementiert werden, und weak ist legal. Dies ist der von Apple empfohlene Ansatz für Delegaten.

\n\n

Warum ist das gut?

\n
    \n
  • Einfachheit und Lesbarkeit.
  • \n
  • Volle ARC-Unterstützung.
  • \n
  • Keine Notwendigkeit für @objc.
  • \n
\n\n

Nachteile?

\n
    \n
  • Sie verlieren die Möglichkeit, das Protokoll mit einer Struktur zu implementieren. Für Delegaten ist dies jedoch in der Regel nicht erforderlich.
  • \n
\n\n

Lösung Nr. 2: Verwendung eines generischen Wrappers (für exotische Fälle)

\n\n

Was ist, wenn Sie zwingend zulassen müssen, dass das Protokoll sowohl von Klassen als auch von Strukturen implementiert wird, aber dennoch eine schwache Referenz wünschen? Dies kommt selten vor, ist aber möglich. Zum Beispiel, wenn Sie eine Bibliothek schreiben, bei der der Benutzer sowohl eine Klasse als auch eine Struktur übergeben kann. Dann hilft ein Wrapper.

\n\n

Die Idee: Erstellen Sie eine Struktur, die eine schwache Referenz auf das Objekt speichert, das das Protokoll implementiert. Für Klassen – we

Blogs

Buchempfehlungen