Sobes.tech
Middle

Какво е unowned?

sobes.tech AI

Отговор от AI

unowned — това е ключова дума в Swift за обявяване на слабата връзка. Използва се, когато два обекта имат силна връзка и техните жизнени цикли зависят един от друг, но искаме да избегнем циклични препратки, които могат да попречат на освобождаването на паметта.

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

  • Неопционална: unowned препратката гарантирано няма да бъде nil през целия живот на обекта, към който сочи.
  • Силна връзка: Използва се, когато един обект притежава друг и те винаги съществуват заедно.
  • При освобождаване: Ако обектът, към който сочи unowned препратката, бъде освободен преди да бъде използвана препратката, това ще доведе до срив на приложението (runtime error). Трябва да се уверите, че обектът, към който сочи unowned препратката, съществува по-дълго от самата препратка.
  • Приложение: Често се използва за делегати, когато делегатът винаги съществува по-дълго от обекта, който го извиква, или в затваряния, за да се избегнат циклични препратки към self, когато затварянето не хваща силна препратка към self.

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

// swift
class MyClass {
    var name: String
    var closure: (() -> Void)?

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

    func setupClosure() {
        closure = { [unowned self] in // Използване на unowned self
            print("My name is \(self.name)")
        }
    }

    deinit {
        print("\(name) deinitialized")
    }
}

Пример за използване за делегат (макар че weak по-често се използва за делегати, unowned също е възможен, ако делегатът гарантирано живее по-дълго):

// swift
protocol MyDelegate: AnyObject { // AnyObject изисква референтен тип
    func doSomething()
}

class DataSource {
    unowned var delegate: MyDelegate // unowned препратка към делегата

    init(delegate: MyDelegate) {
        self.delegate = delegate
    }

    func performAction() {
        delegate.doSomething()
    }

    deinit {
        print("DataSource deinitialized")
    }
}

class MyController: MyDelegate {
    var dataSource: DataSource?

    override init() {
        super.init()
        dataSource = DataSource(delegate: self)
    }

    func doSomething() {
        print("Delegate method called")
    }

    deinit {
        print("MyController deinitialized")
    }
}

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