Sobes.tech
Middle

Was ist unowned in Swift und wie wird es verwendet?

sobes.tech KI

Antwort von AI

Unowned-Referenz (schwache indirekte Besitznahme) in Swift wird verwendet, um starke Besitzzyklus (retain cycles) zu vermeiden, wenn zwei Objekte sich gegenseitig stark referenzieren, was ihre Freigabe aus dem Speicher verhindert.

Eigenschaften von unowned:

  • Garantiert, dass das Objekt, auf das sich die unowned-Referenz bezieht, immer existiert bis zum Zeitpunkt der Nutzung dieser Referenz.
  • Wenn versucht wird, nach der Freigabe des verbundenen Objekts auf die unowned-Referenz zuzugreifen, tritt ein Laufzeitfehler (runtime crash) auf.
  • Wird verwendet, wenn der Lebenszyklus des referenzierenden Objekts nicht länger ist als der des referenzierten Objekts. Mit anderen Worten, die unowned-Referenz macht das Objekt nicht stark.

Beispiel für die Verwendung in einer Closure-Erfassung:

class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) wird deinitialisiert")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Unowned-Referenz auf Customer

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }

    deinit {
        print("Karte #\(number) wird deinitialisiert")
    }
}

var john: Customer? // Optionaler Customer für Freigabe
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

// Das Zuweisen von nil an john führt zur Freigabe von Customer und Card,
// da kein starker Besitzzyklus besteht
john = nil 

Ein weiteres Beispiel - Verwendung von unowned in einer Closure-Erfassungsliste:

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = { [unowned self] in // Verwendung von unowned self
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) wird deinitialisiert")
    }
}

var paragraph: HTMLElement? // Optionales HTML-Element
paragraph = HTMLElement(name: "p", text: "Hallo Welt")
print(paragraph!.asHTML())

// Das Zuweisen von nil wird HTMLElement freigeben, da die Closure es nicht stark hält
paragraph = nil

Die Wahl zwischen unowned und weak hängt davon ab, ob die Referenz nil sein kann während der Lebensdauer des Objekts. Wenn die Referenz niemals nil werden kann vor der Freigabe des Objekts, verwenden Sie unowned. Wenn sie nil werden kann, verwenden Sie weak.