Sobes.tech
Middle

Kas yra unowned Swift kalboje ir kaip jis naudojamas?

sobes.tech AI

Atsakymas iš AI

Neposedinė nuoroda (silpnas netiesioginis nuosavybės valdymas) Swift naudojama siekiant išvengti stiprių nuorodų ciklų (retain cycles), kai du objektai stipriai nurodo vienas į kitą, taip užkertant kelią jų atlaisvinimui iš atminties.

unowned ypatybės:

  • Garantuoja, kad objektas, į kurį nukreipia unowned nuoroda, visada egzistuos iki jos naudojimo momento.
  • Jei bandysite pasiekti unowned nuorodą po to, kai susijęs objektas buvo atlaisvintas, įvyks vykdymo klaida (runtime crash).
  • Naudojama, kai nuorodą nurodantis objektas nebus ilgesnis už objektą, į kurį jis nukreipia. Kitaip tariant, unowned nuoroda nepadaro objekto stipresnio.

Pavyzdys naudojant užfiksavimą uždaryme:

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

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

    deinit {
        print("\(name) yra atlaisvinamas")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Unowned nuoroda į Customer

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

    deinit {
        print("Kortelė #\(number) yra atlaisvinama")
    }
}

var john: Customer? // Pasirinktinė Customer
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

// Jei priskirsime nil, Customer ir Card bus atlaisvinti,
// nes nėra stipraus ciklo
john = nil 

Kitas pavyzdys — unowned naudojimas užfiksavime:

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

    lazy var asHTML: () -> String = { [unowned self] in // Naudojant 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) yra atlaisvinamas")
    }
}

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

// Jei priskirsime nil, HTMLElement bus atlaisvintas, nes užfiksavimas jo stipriai nelaiko
paragraph = nil

Pasirinkimas tarp unowned ir weak priklauso nuo to, ar nuoroda gali būti nil gyvenimo ciklo metu. Jei nuoroda niekada negali tapti nil iki objekto atlaisvinimo, naudokite unowned. Jei gali — naudokite weak.