Sobes.tech
Middle

Mi az az unowned a Swift nyelvben, és hogyan használják?

sobes.tech MI

Válasz az MI-től

Swiftben az unowned referencia (gyenge közvetett tulajdonlás) arra szolgál, hogy elkerüljük a erős tulajdonlási ciklusokat (retain cycles), amikor két objektum erősen hivatkozik egymásra, ezáltal megakadályozva azok memória felszabadítását.

Az unowned jellemzői:

  • Biztosítja, hogy az objektum, amelyre az unowned hivatkozás mutat, mindig létezik a hivatkozás használatáig.
  • Ha megpróbál hozzáférni az unowned hivatkozáshoz azután, hogy a kapcsolódó objektum felszabadult, akkor futásidejű hiba (runtime crash) történik.
  • Akkor használjuk, amikor a hivatkozó objektum életciklusa nem hosszabb, mint a hivatkozott objektumé. Más szóval, az unowned nem teszi erőssé az objektumot.

Példa az unowned használatára záradékban:

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

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

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

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Unowned hivatkozás Customer-re

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

    deinit {
        print("Kártya #\(number) felszabadul")
    }
}

var john: Customer? // Opciókénti Customer a felszabadításhoz
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

// Az nil értékadás a john-nak felszabadítja a Customer-t és a Card-ot,
// mivel nincs erős tulajdonlási ciklus
john = nil 

Másik példa - unowned használata záradékban:

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

    lazy var asHTML: () -> String = { [unowned self] in // unowned self használata
        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) felszabadul")
    }
}

var paragraph: HTMLElement? // Opcionális HTML elem
paragraph = HTMLElement(name: "p", text: "szia világ")
print(paragraph!.asHTML())

// Az nil értékadás felszabadítja a HTMLElement-et, mivel a záradék nem tartja erősen
paragraph = nil

A unowned és weak közötti választás attól függ, hogy a referencia nil-vé válhat-e az objektum életciklusa során. Ha a referencia soha nem válhat nil-vé az objektum felszabadítása előtt, akkor használja az unowned-t. Ha igen, akkor a weak-et.