Sobes.tech
Middle

A cosa serve il tipo di riferimenti unowned?

sobes.tech AI

Risposta dell'AI

Le referenze unowned sono necessarie per risolvere i cicli di riferimento (retention cycles) tra oggetti, quando entrambi gli oggetti hanno un riferimento forte tra loro, ma uno di essi ha un ciclo di vita più breve o uguale all'altro.

unowned viene usato quando si sa che l'oggetto referenziato non sarà nil durante tutta la vita dell'oggetto che contiene il riferimento. A differenza di weak, l'accesso a una referenza unowned non utilizza Optional. Se l'oggetto a cui si riferisce unowned viene deallocato prima dell'oggetto con la referenza unowned, si verificherà un crash.

Esempio di utilizzo in closure:

class Person {
    let name: String
    var apartment: Apartment?

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

    deinit {
        print("\(name) viene de-inizializzato")
    }
}

class Apartment {
    let unit: String
    // Si usa `unowned` perché si sa che
    // l'Apartment non può esistere senza Person
    // (in questo contesto). Person può essere nil,
    // ma se l'Apartment esiste, anche Person esiste.
    unowned let tenant: Person

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

    deinit {
        print("Appartamento \(unit) viene de-inizializzato")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
// In questo esempio, tenant può essere nil, quindi
// si usa una referenza unowned
unit4A = Apartment(unit: "4A", tenant: john!)

john!.apartment = unit4A

// Rimuoviamo le referenze forti per verificare la deallocazione
john = nil
unit4A = nil

In questo esempio, Person ha una referenza forte su Apartment (var apartment: Apartment?). Apartment potrebbe avere una referenza forte su Person, creando un ciclo. Tuttavia, in questo contesto, Apartment non può esistere senza Person (che lo affitta), quindi la referenza da Apartment a Person è unowned. Così, quando si imposta john = nil, Person viene deallocato, e di conseguenza (poiché non ci sono referenze forti su Apartment) anche Apartment viene deallocato.

Principali differenze con weak:

  • Ciclo di vita: unowned viene usato quando l'oggetto referenziato ha un ciclo di vita uguale o più lungo. weak viene usato quando l'oggetto referenziato può essere deallocato prima.
  • Optional: unowned non è opzionale (a meno che non sia dichiarato come unowned optional). weak è sempre opzionale.
  • Sicurezza: L'accesso a una proprietà con riferimento unowned a un oggetto già deallocato causerà un crash. L'accesso a una referenza weak restituirà nil.

Dunque, unowned è una referenza non proprietaria (non-owning) che viene usata quando si garantisce l'esistenza dell'oggetto referenziato finché l'oggetto con la referenza unowned esiste.