Sobes.tech
Middle

Do czego służy typ referencji unowned?

sobes.tech AI

Odpowiedź od AI

Odwołania unowned są potrzebne do rozwiązania cykli referencyjnych (retention cycles) między obiektami, gdy oba obiekty mają silne odwołanie do siebie, ale jeden z nich ma krótszy lub równy cykl życia w porównaniu do drugiego.

unowned jest używane, gdy wiadomo, że obiekt referencyjny nie będzie nil przez cały czas życia obiektu zawierającego odwołanie. W przeciwieństwie do weak, dostęp do odwołania unowned nie wymaga Optional. Jeśli obiekt, na który wskazuje unowned, zostanie zwolniony przed obiektem z odwołaniem unowned, spowoduje to awarię (crash).

Przykład użycia w zamknięciach:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
        print("\(name) jest inicjalizowany")
    }

    deinit {
        print("\(name) jest deinitializowany")
    }
}

class Apartment {
    let unit: String
    // Używamy `unowned`, ponieważ wiadomo, że
    // Apartment nie może istnieć bez Person
    // (w tym kontekście). Person może być nil,
    // ale jeśli Apartment istnieje, Person też istnieje.
    unowned let tenant: Person

    init(unit: String, tenant: Person) {
        self.unit = unit
        self.tenant = tenant
        print("Mieszkanie \(unit) jest inicjalizowane")
    }

    deinit {
        print("Mieszkanie \(unit) jest deinitializowane")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
// W tym przykładzie, tenant może być nil, dlatego
// używamy referencji unowned
unit4A = Apartment(unit: "4A", tenant: john!)

john!.apartment = unit4A

// Zerwijmy silne odwołania, aby sprawdzić deallokację
john = nil
unit4A = nil

W tym przykładzie, Person ma silne odwołanie do Apartment (var apartment: Apartment?). Apartment mógłby mieć silne odwołanie do Person, co tworzyłoby cykl. Jednak, ponieważ w tym kontekście Apartment nie może istnieć bez Person (który go wynajmuje), odwołanie od Apartment do Person jest unowned. W ten sposób, gdy ustawimy john = nil, Person jest deallokowany, a następnie (ponieważ nie ma silnych odwołań do Apartment) również Apartment jest deallokowany.

Główne różnice w stosunku do weak:

  • Cykl życia: unowned jest używane, gdy obiekt referencyjny ma taki sam lub dłuższy cykl życia. weak jest używane, gdy obiekt referencyjny może być wcześniej zwolniony.
  • Optional: unowned nie jest Optional (chyba że jest zadeklarowane jako unowned optional). weak zawsze jest Optional.
  • Bezpieczeństwo: Dostęp do właściwości z odwołaniem unowned do już zwolnionego obiektu spowoduje crash. Dostęp do weak zwróci nil.

Podsumowując, unowned to referencja nieposiadająca (non-owning), używana, gdy gwarantuje się istnienie obiektu referencyjnego do czasu istnienia obiektu z odwołaniem unowned.