Sobes.tech
Middle

La ce folosește tipul de referințe unowned?

sobes.tech AI

Răspuns de la AI

Referințele unowned sunt necesare pentru rezolvarea ciclurilor de referință (retention cycles) între obiecte, atunci când ambele obiecte au o referință puternică unul către celălalt, dar unul dintre obiecte are un ciclu de viață mai scurt sau egal cu celălalt.

unowned este utilizat atunci când se știe că obiectul referențiat nu va fi nil pe durata întregii vieți a obiectului care conține referința. Spre deosebire de weak, accesul la o referință unowned nu folosește Optional. Dacă obiectul la care se face referire unowned este deallocat înaintea obiectului cu referința unowned, va avea loc o eroare de tip crash.

Exemplu de utilizare în closures:

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

    init(name: String) {
        self.name = name
        print("\(name) este inițializat")
    }

    deinit {
        print("\(name) este dezinitalizat")
    }
}

class Apartment {
    let unit: String
    // Se folosește `unowned` deoarece se știe că
    // Apartment nu poate exista fără Person
    // (în acest context). Person poate fi nil,
    // dar dacă Apartment există, și Person există.
    unowned let tenant: Person

    init(unit: String, tenant: Person) {
        self.unit = unit
        self.tenant = tenant
        print("Apartament \(unit) este inițializat")
    }

    deinit {
        print("Apartament \(unit) este dezinitalizat")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
// În acest exemplu, tenant poate fi nil, de aceea
// se folosește o referință unowned
unit4A = Apartment(unit: "4A", tenant: john!)

john!.apartment = unit4A

// Întrerupem referințele puternice pentru a verifica deallocarea
john = nil
unit4A = nil

În acest exemplu, Person are o referință puternică către Apartment (var apartment: Apartment?). Apartment ar putea avea o referință puternică către Person, ceea ce ar crea un ciclu. Totuși, în acest context, Apartment nu poate exista fără Person (cel care îl închiriază), așa că referința de la Apartment către Person este unowned. Astfel, când se setează john = nil, Person este deallocat, iar apoi (deoarece nu există referințe puternice către Apartment) și Apartment este deallocat.

Principalele diferențe față de weak:

  • Durata de viață: unowned este folosit atunci când obiectul referențiat are o durată de viață egală sau mai lungă. weak este folosit atunci când obiectul referențiat poate fi deallocat mai devreme.
  • Optional: unowned nu este Optional (cu excepția cazului în care este declarat ca unowned optional). weak este întotdeauna Optional.
  • Siguranță: Accesul la o proprietate cu referință unowned către un obiect deja deallocat va duce la o eroare de tip crash. Accesul la o referință weak va returna nil.

Așadar, unowned este o referință non-owning (fără proprietate), utilizată atunci când se garantează existența obiectului referențiat până când obiectul cu referința unowned există.