Sobes.tech
Middle

Welche Arten von Verweisen gibt es in Swift?

sobes.tech KI

Antwort von AI

In Swift gibt es drei Hauptarten von Referenzen auf Klasseninstanzen:

  1. Starke Referenz (Strong Reference):

    • Dies ist der Standardreferenztyp.
    • Eine starke Referenz erhöht den Referenzzähler des Objekts.
    • Das Objekt wird nicht aus dem Speicher freigegeben, solange mindestens eine starke Referenz besteht.
    • Der Hauptgrund für Speicherlecks bei zyklischen starken Referenzen (strong reference cycles).
    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) wird deinitialisiert") }
    }
    
    var reference1: Person? = Person(name: "John")
    // reference1 ist jetzt eine starke Referenz, der Referenzzähler von Person erhöht sich
    
  2. Schwache Referenz (Weak Reference):

    • Wird mit dem Schlüsselwort weak deklariert.
    • Eine schwache Referenz erhöht den Referenzzähler des Objekts nicht.
    • Wird verwendet, um strong reference cycles zu verhindern.
    • Ist immer optional (Optional), da das Objekt, auf das die schwache Referenz zeigt, jederzeit deinitialisiert werden kann. Wenn das Objekt deinitialisiert wird, wird die schwache Referenz automatisch nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Schwache Referenz
        init(unit: String) { self.unit = unit }
        deinit { print("Apartment \(unit) wird deinitialisiert") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Wenn Apartment eine starke Referenz auf Person hätte
    unit4A?.tenant = john   // Schwache Referenz
    
    // Nach Entfernen der starken Referenzen werden die Objekte deinitialisiert
    john = nil
    unit4A = nil
    // Ausgabe: "John wird deinitialisiert", "Apartment 4A wird deinitialisiert"
    // Wenn tenant eine starke Referenz wäre, würde es zu einem Speicherleck kommen (zyklischer Zyklus)
    
  3. Unbesitzte Referenz (Unowned Reference):

    • Wird mit dem Schlüsselwort unowned deklariert.
    • Ähnlich wie die schwache Referenz, erhöht sie den Referenzzähler des Objekts nicht.
    • Wird ebenfalls verwendet, um strong reference cycles zu verhindern.
    • Im Gegensatz zu weak ist sie nicht optional (Optional) und geht davon aus, dass das referenzierte Objekt während der gesamten "Lebensdauer" der unbesitzten Referenz existiert.
    • Wenn das referenzierte Objekt vor der unbesitzten Referenz deinitialisiert wird, tritt ein Laufzeitfehler (runtime error) auf.
    • Geeignet für Situationen, in denen ein Objekt immer existiert, solange ein anderes verbundenes Objekt existiert (z.B. "Eltern-Kind", wobei der Elternteil das Kind besitzt, aber das Kind den Elternteil nicht stark besitzt).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) { self.name = name }
        deinit { print("\(name) wird deinitialisiert") }
    }
    
    class CreditCard {
        let number: Int
        unowned let customer: Customer // Unbesitzte Referenz
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Sichere Zuweisung im init
        }
        deinit { print("Karte #\(number) wird deinitialisiert") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Entfernen der starken Referenz auf Customer
    john = nil
    // Ausgabe: "John Doe wird deinitialisiert", "Karte #1234567890123456 wird deinitialisiert"
    // Die unbesitzte Referenz in CreditCard war gültig, solange customer existierte.
    // Wenn CreditCard länger lebt als Customer und wir versuchen, auf customer über die unbesitzte Referenz zuzugreifen, tritt ein Fehler auf.
    

Hauptunterschied zwischen weak und unowned:

  • weak: Das Objekt kann nil sein. Verwenden Sie es, wenn die Lebensdauer der Objekte nicht strikt verbunden ist (eines kann ohne das andere existieren).
  • unowned: Das Objekt kann nach der Initialisierung nicht nil sein. Verwenden Sie es, wenn Sie sicher sind, dass das referenzierte Objekt mindestens so lange existiert, wie das referenzierende Objekt.