Sobes.tech
Middle

Čo je unowned v jazyku Swift a ako sa používa?

sobes.tech AI

Odpoveď od AI

Neposedná referencia (slabé nepriamé vlastníctvo) v Swift sa používa na vyhýbanie sa cyklom silného vlastníctva (retain cycles), keď si dva objekty navzájom silno odkazujú, čím bránia ich uvoľneniu z pamäte.

Charakteristiky unowned:

  • Zaručuje, že objekt, na ktorý sa odkazuje unowned referencia, vždy existuje do okamihu použitia tejto referencie.
  • Ak sa pokúsite získať prístup k unowned referencii po tom, čo je s ňou spojený objekt uvoľnený, dôjde k runtime chybe (runtime crash).
  • Používa sa, keď životný cyklus odkazovaného objektu nie je dlhší ako životný cyklus objektu, ktorý naň odkazuje. Teda, unowned referencia ne robí objekt silnejším.

Príklad použitia pri zachytení uzávierky:

class Customer {
    let name: String
    var card: CreditCard?

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

    deinit {
        print("\(name) sa uvoľňuje")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Unowned referencia na Customer

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }

    deinit {
        print("Karta #\(number) sa uvoľňuje")
    }
}

var john: Customer? // Voliteľný Customer pre možnosť uvoľnenia
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

// Priradenie nil k john povedie k uvoľneniu Customer a Card,
// pretože neexistuje cyklus silného vlastníctva
john = nil 

Iný príklad - použitie unowned v zozname zachytenia uzávierky:

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

    lazy var asHTML: () -> String = { [unowned self] in // Použitie 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) sa uvoľňuje")
    }
}

var paragraph: HTMLElement? // Voliteľný HTML prvok
paragraph = HTMLElement(name: "p", text: "hello world")
print(paragraph!.asHTML())

// Priradenie nil uvoľní HTMLElement, pretože uzávierka ho nedrží silno
paragraph = nil

Voľba medzi unowned a weak závisí od toho, či referenciu môže byť nil počas životnosti objektu. Ak referenciu nikdy nemôže byť nil pred uvoľnením objektu, použite unowned. Ak môže - použite weak.