Sobes.tech
Middle

Qual è la differenza tra link Wick e link Anound?

sobes.tech AI

Risposta dell'AI

Il riferimento debole (weak) è un riferimento che non aumenta il contatore di riferimenti dell'oggetto. Viene utilizzato per prevenire cicli di riferimenti forti, ad esempio tra un delegato e il suo proprietario. Se l'oggetto a cui punta il riferimento debole viene deallocato, il riferimento debole diventa automaticamente nil.

Il riferimento non posseduto (unowned) è anch'esso un riferimento che non aumenta il contatore di riferimenti dell'oggetto. La differenza con weak è che unowned non può essere opzionale (Optional) e deve sempre puntare a un oggetto esistente. Se l'oggetto a cui punta il riferimento unowned viene deallocato prima che il riferimento smetta di esistere, l'accesso a tale riferimento causerà un errore di runtime (errore fatale). Viene usato quando il ciclo di vita dell'oggetto collegato è garantito essere più lungo o uguale a quello dell'oggetto con il riferimento unowned (ad esempio, in un ciclo di riferimenti forti in cui uno degli oggetti ha un ciclo di vita chiaramente definito).

Confronto:

Caratteristica weak unowned
Non possedente
Aumenta il contatore No No
Può essere nil Sì (si azzera automaticamente) No (deve puntare a un oggetto)
Sicurezza Più sicura in caso di deallocazione Meno sicura (errore fatale all'accesso a oggetto deallocato)
Tipo Deve essere opzionale Non può essere opzionale (per default)
Uso Prevenire cicli di riferimenti forti, dove l'oggetto può cessare di esistere prima Prevenire cicli di riferimenti forti, dove l'oggetto garantisce la propria esistenza

Esempio di utilizzo di weak per prevenire un ciclo di riferimenti forti:

class Person {
    let name: String
    weak var apartment: Apartment? // riferimento debole per evitare ciclo di ritenzione

    init(name: String) {
        self.name = name
        print("\(name) viene inizializzato")
    }

    deinit {
        print("\(name) viene deinizializzato")
    }
}

class Apartment {
    let unit: String
    var occupant: Person?

    init(unit: String) {
        self.unit = unit
        print("Appartamento \(unit) viene inizializzato")
    }

    deinit {
        print("Appartamento \(unit) viene deinizializzato")
    }
}

Esempio di utilizzo di unowned nel contesto di cattura di self in una chiusura:

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

    lazy var asHTML: () -> String = {
        [unowned self] in // self non posseduto per evitare ciclo di ritenzione con la chiusura
        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) viene deinizializzato")
    }
}