Sobes.tech
Middle

За какво е нужен типът на референциите unowned?

sobes.tech AI

Отговор от AI

unowned препратки са необходими за разрешаване на циклични препратки (retain cycles) между обекти, когато и двата обекта имат силна препратка един към друг, но един от тях има по-кратък или равен жизнен цикъл спрямо другия.

unowned се използва, когато е известно, че препратеният обект няма да бъде nil през цялото време на живота на обекта, който съдържа препратката. За разлика от weak, при unowned достъпът до препратката не използва Optional. Ако обектът, към който се препраща с unowned, бъде деалокирана преди обекта с unowned препратка, ще настъпи crash.

Пример за използване в затваряния:

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

    init(name: String) {
        self.name = name
        print("\(name) се инициализира")
    }

    deinit {
        print("\(name) се деинициализира")
    }
}

class Apartment {
    let unit: String
    // Използваме `unowned`, тъй като е известно, че
    // Apartment не може да съществува без Person
    // (в този контекст). Person може да бъде nil,
    // но ако Apartment съществува, Person също съществува.
    unowned let tenant: Person

    init(unit: String, tenant: Person) {
        self.unit = unit
        self.tenant = tenant
        print("Apartment \(unit) се инициализира")
    }

    deinit {
        print("Apartment \(unit) се деинициализира")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
// В този пример tenant може да бъде nil, затова `unowned`
unit4A = Apartment(unit: "4A", tenant: john!)

john!.apartment = unit4A

// Разкъсваме силните препратки, за да проверим деалокацията
john = nil
unit4A = nil

В този пример Person има силна препратка към Apartment (var apartment: Apartment?). Apartment може да има силна препратка към Person, което ще доведе до цикъл. Въпреки това, тъй като в този контекст Apartment логически не може да съществува без Person (който го наема), връзката от Apartment към Person се прави с unowned. Така, при нулиране на john = nil, Person се деалокира, а след това (тъй като няма силни препратки към Apartment) и Apartment се деалокира.

Основните разлики от weak:

  • Животен цикъл: unowned се използва, когато препратеният обект има същия или по-дълъг жизнен цикъл. weak се използва, когато препратеният обект може да бъде деалокирана по-рано.
  • Optional: unowned не е Optional (освен ако не е обявен като unowned optional). weak винаги е Optional.
  • Безопасност: Достъпът до свойство с unowned препратка към вече деалокирал се обект ще доведе до crash. Достъпът до weak препратка ще върне nil.

Така, unowned е не-отстъпваща (non-owning) препратка, която се използва, когато се гарантира съществуването на препратения обект, докато съществува обект с unowned препратка.