Sobes.tech
Middle

Šta je unowned u jeziku Swift i kako se koristi?

sobes.tech АИ

Одговор од АИ

Neposedovna referenca (slabo posredno vlasništvo) u Swift-u se koristi za izbegavanje ciklusa snažnog vlasništva (retain cycles), kada dva objekta snažno ukazuju jedan na drugog, sprečavajući njihovo oslobađanje iz memorije.

Karakteristike unowned:

  • Garantuje da objekat na koji se odnosi unowned referenca, uvek postoji do trenutka korišćenja te reference.
  • Ako pokušate da pristupite unowned referenci nakon što je povezani objekat oslobođen, doći će do greške u izvršenju (runtime crash).
  • Koristi se kada životni vek referenciranog objekta nije duži od životnog veka objekta koji ga referencira. Dakle, unowned referenca ne čini objekat snažnijim.

Primer upotrebe u hvatanju zatvaranja:

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

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

    deinit {
        print("\(name) se oslobađa")
    }
}

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

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

    deinit {
        print("Karta #\(number) se oslobađa")
    }
}

var john: Customer? // Opcionalni Customer za mogućnost oslobađanja
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

// Dodeljivanje nil john će dovesti do oslobađanja Customer i Card,
// jer nema ciklusa snažnog vlasništva
john = nil 

Drugi primer - korišćenje unowned u listi za hvatanje zatvaranja:

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

    lazy var asHTML: () -> String = { [unowned self] in // Korišćenje 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) se oslobađa")
    }
}

var paragraph: HTMLElement? // Opcionalni HTML element
paragraph = HTMLElement(name: "p", text: "hello world")
print(paragraph!.asHTML())

// Dodeljivanje nil će osloboditi HTMLElement, jer zatvaranje ga ne drži snažno
paragraph = nil

Izbor između unowned i weak zavisi od toga da li referenca može biti nil tokom životnog veka objekta. Ako referenca nikada ne može postati nil pre oslobađanja objekta, koristite unowned. Ako može - koristite weak.