Sobes.tech
Middle

Каква е разликата между Wick връзки и Anound връзки?

sobes.tech AI

Отговор от AI

Wick-ссылка (weak) — това е невладееща препратка. Тя не увеличава броя на препратките към обекта. Използва се за предотвратяване на цикли на силни препратки, например между делегат и неговия собственик. Ако обектът, към който сочи слабата препратка, бъде деалокиран, слабата препратка автоматично става nil.

Unowned-ссылка (unowned) — също е невладееща препратка и не увеличава броя на препратките към обекта. Разликата от weak е, че unowned не може да бъде опционална (Optional) и винаги трябва да сочи към съществуващ обект. Ако обектът, към който сочи unowned препратката, бъде деалокиран преди препратката да престане да съществува, опитът за достъп до тази препратка ще доведе до грешка при изпълнение (фатална грешка). Използва се там, където жизненият цикъл на свързания обект е гарантирано по-дълъг или равен на жизнения цикъл на обекта с unowned-препратка (например, цикъл на силни препратки, където един от обектите има ясно определен жизнен цикъл).

Сравнение:

Характеристика weak unowned
Невладееща Да Да
Увеличава SC Не Не
Може да бъде nil Да (автоматично нулирано) Не (трябва да сочи към обект)
Безопасност По-безопасна при възможно деалокиране По-малко безопасна (фатална грешка при достъп до деалокирания)
Тип Трябва да бъде опционална Не може да бъде опционална (по подразбиране)
Използване Предотвратяване на цикли на силни препратки, където обектът може да престане да съществува по-рано Предотвратяване на цикли на силни препратки, където обектът е гарантирано съществуващ

Пример за използване на weak за предотвратяване на цикъл на силни препратки:

class Person {
    let name: String
    weak var apartment: Apartment? // слаб препратка за избягване на цикъл

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

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

class Apartment {
    let unit: String
    var occupant: Person?

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

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

Пример за използване на unowned в контекста на захващане на self в затваряне:

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

    lazy var asHTML: () -> String = {
        [unowned self] in // 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) е деинициализиран")
    }
}