Unowned Reference: cos'è, sintassi e utilizzo nelle applicazioni mobili

Autore: IT Sectr Pubblicato: 2026-03-30 Tempo di lettura: 9 min

Unowned Reference (riferimento non posseduto) è un riferimento non proprietario in Swift che non aumenta il retain count dell'oggetto e, a differenza di weak, non viene impostato a nil dopo la liberazione dell'oggetto. Secondo Apple Swift Language Guide, 2026, unowned viene utilizzato quando è garantito che l'oggetto viva almeno quanto l'oggetto che lo riferisce. A differenza di Weak Reference, unowned non richiede unwrap — è un tipo non opzionale, che rende il codice più pulito ma pone la responsabilità della garanzia del ciclo di vita sullo sviluppatore.

Punti Chiave

  • Unowned Reference — riferimento non possessivo senza azzeramento automatico; non opzionale, non aumenta il retain count
  • Garanzia — utilizzato quando l'oggetto è garantito a non essere liberato prima dell'oggetto che lo riferisce
  • Differenza da weak — unowned non si azzera a nil (rischio di crash), weak si azzera (sicuro)
  • Scenari — genitore-figlio con garanzia di vita, closure con unowned self, singleton e Service Locator
  • Rischio — accedere a un oggetto unowned liberato causa un crash a runtime (EXC_BAD_ACCESS)

Cos'è Unowned Reference?

Unowned Reference è un riferimento non proprietario a un oggetto in ARC che non aumenta il suo retain count. A differenza di weak, un riferimento unowned non viene azzerato dopo la deallocazione dell'oggetto: continua a puntare a memoria già liberata. Accedere a tale riferimento causa un crash a runtime con EXC_BAD_ACCESS.

Il termine “non posseduto” riflette la semantica: l'oggetto esiste, ma nessuno è responsabile del suo ciclo di vita. Lo sviluppatore dichiara esplicitamente: “garantisco che questo oggetto sarà vivo finché lo riferisco.” Il compilatore non verifica questa garanzia — è un contratto a livello di sviluppatore.

Secondo Swift.org Documentation, 2026, i riferimenti unowned sono preferiti a weak negli scenari con ciclo di vita garantito perché: non richiedono un tipo opzionale (codice più pulito), non richiedono unwrap (meno force-unwrap o guard let), e non hanno overhead di manutenzione di una tabella weak di azzeramento. Tuttavia, qualsiasi violazione del contratto risulta in un crash.

Sintassi di unowned in Swift

In Swift, i riferimenti unowned sono dichiarati con la parola chiave unowned prima di let o var. A differenza di weak, unowned può essere sia let che var, e non richiede un tipo opzionale. Questa proprietà rende unowned conveniente per riferimenti che non possono essere nil per logica di dominio.

swift
class Country {
    let name: String
    var capital: City!           // verrà impostato dopo l'inizializzazione
    init(name: String) { self.name = name }
}

class City {
    let name: String
    unowned let country: Country   // ✅ unowned let — garanzia di vita

    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}

// Utilizzo
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// ✅ Country → City (strong), City → Country (unowned) — nessun retain cycle

In questo esempio, City unowned let country — una città non può esistere senza un paese. Se il paese scompare, la città (e il riferimento) perdono il loro significato. Semanticamente, questo è un caso ideale per unowned: la garanzia del ciclo di vita esiste, l'opzionale non è necessario, il retain cycle non si verifica.

unowned var

unowned var è permesso ma meno comune. Viene utilizzato quando il riferimento può essere sostituito (ad esempio, riassegnare un figlio a un genitore diverso). Al momento della riassegnazione, la deallocazione dell'oggetto vecchio è responsabilità del proprietario esterno.

Unowned Optional

In Swift 5.0+, è stato introdotto il supporto per unowned opzionale (unowned let x: Type?). Questo è un compromesso: unowned garantisce che se il riferimento non è nil, l'oggetto è vivo. Il comportamento alla deallocazione è un crash, come con unowned normale.

Unowned vs Weak: quando usare cosa

La scelta tra unowned e weak è una delle decisioni frequenti quando si progetta l'architettura Swift. Esaminiamo i criteri e le raccomandazioni per ogni caso.

CriterioWeakUnowned
OpzionaleSì (Type?)No (Type)
Azzeramento alla deallocazioneAuto a nilNo (rischio di puntatore pendente)
Tipo (let/var)Solo varlet o var
PrestazioniOverhead della tabella weakMinimo (puntatore semplice)
SicurezzaSicuro (nil verificato)Rischio di EXC_BAD_ACCESS
Garanzia del ciclo di vitaNon richiestaGaranzia esplicita richiesta

Regola Pratica

Usa weak se c'è anche il minimo dubbio sul ciclo di vita dell'oggetto. Weak è sicuro, chiaro e non richiede prove. Usa unowned solo quando puoi escludere tutti gli scenari in cui l'oggetto potrebbe essere deallocato prima. Casi tipici: un figlio che non esiste senza un genitore; una closure che si esegue in modo sincrono; accesso a un oggetto all'interno del suo inizializzatore.

Secondo Airbnb Swift Style Guide, 2025, in grandi basi di codice si consiglia di usare weak per impostazione predefinita e unowned solo con un commento esplicito che spieghi la garanzia del ciclo di vita. Ciò riduce il rischio di crash non ovvi durante il refactoring.

Unowned self nelle Closure

Le closure sono il secondo caso d'uso più frequente per unowned dopo le relazioni genitore-figlio. La lista di cattura [unowned self] viene utilizzata quando è garantito che self sopravviva alla closure. Esaminiamo scenari corretti e errati.

Quando unowned self è sicuro

Closure sincrone — sorted, filter, map. Vengono eseguite immediatamente nel thread corrente, self è sicuramente vivo. Una lista di cattura con unowned è accettabile qui e produce codice più pulito.

swift
class DataProcessor {
    var items: [Int] = [3, 1, 4, 1, 5]

    func processSorted() {
        // ✅ unowned self — sorted viene eseguito in modo sincrono, self è garantitamente vivo
        let sorted = items.sorted { [unowned self] a, b in
            return self.customCompare(a, b)
        }
    }

    func customCompare(_ a: Int, _ b: Int) -> Bool { return a < b }
}

Quando unowned self è pericoloso

Closure asincrone — con ritardi, richieste di rete, animazioni. Self può essere deallocato tra la pianificazione della closure e la sua esecuzione. Qui unowned self porta a un crash. Usa [weak self].

swift
class NetworkLoader {
    func loadData() {
        // ❌ PERICOLOSO: unowned self in closure asincrona
        URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
            self.handleResponse(data)  // CRASH se self viene liberato
        }.resume()
    }

    func handleResponse(_ data: Data?) { }

    // ✅ CORRETTO: weak self + guard
    func loadDataSafe() {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
            guard let self else { return }
            self.handleResponse(data)
        }.resume()
    }
}

Ricorda la regola: unowned self — solo per closure sincrone che vengono eseguite immediatamente. Per closure asincrone, usa sempre weak self + guard let. Eccezione: se mantieni esplicitamente un riferimento all'oggetto fino al completamento della closure (ad esempio, mantenendo un riferimento forte in un'altra variabile).

Rischi di unowned e come evitarli

Unowned è uno strumento potente ma pericoloso. Esaminiamo scenari reali in cui unowned può portare a crash e metodi per minimizzare il rischio.

Refactoring e Cambiamento delle Garanzie

Il rischio principale di unowned è un cambiamento nella logica di business che invalida la garanzia del ciclo di vita. Uno sviluppatore rifattorizza il codice: cambia la proprietà, introduce deallocazione differita, aggiunge caching — e il riferimento unowned diventa una bomba a orologeria. Il compilatore non avviserà — solo un crash sul dispositivo dell'utente.

Raccomandazione: usa unowned solo quando la garanzia del ciclo di vita è ovvia e documentata. Aggiungi un commento a ogni unowned: perché questo riferimento è sicuro e in quali condizioni potrebbe essere violato.

Unowned nelle Gerarchie UIKit

UIKit è un'area ad alto rischio per unowned. Un ViewController può essere deallocato in qualsiasi momento durante la navigazione (pop, dismiss), scaricamento della memoria o cambi di orientamento. Se passi un ViewController a una closure con unowned self, self potrebbe essere nil al ritorno dallo sfondo o al completamento di un'animazione.

Migliori Pratiche

Per ridurre il rischio quando usi unowned, segui queste regole:

  • Preferisci weak per impostazione predefinita — weak è sicuro, unowned è un'ottimizzazione, non uno standard
  • Documenta le garanzie — per ogni unowned, scrivi un commento con giustificazione
  • Evita unowned in ViewController — il ciclo di vita di UIKit è imprevedibile per le garanzie unowned
  • Usa unowned solo per closure sincrone — sorted, filter, map sono candidati sicuri
  • Controlla durante la revisione del codice — ogni unowned richiede una giustificazione dall'autore del codice
  • Migra a weak al minimo dubbio — la perdita in leggibilità (un guard let) è minore di un crash in produzione
swift
// Esempio: riferimento unowned documentato con giustificazione esplicita
class InvoiceLineItem {
    let productName: String
    let price: Decimal

    // unowned Invoice — InvoiceLineItem non può esistere senza Invoice.
    // Invoice crea Item e lo rimuove quando viene eliminato.
    // Garanzia: Invoice vive almeno quanto Item.
    unowned let invoice: Invoice

    init(productName: String, price: Decimal, invoice: Invoice) {
        self.productName = productName
        self.price = price
        self.invoice = invoice
    }
}

// Questa è una garanzia forte: Invoice rimuove tutti gli Item in deinit.
// violare la garanzia = un bug nella logica di business che deve essere corretto.

Documentare le garanzie è uno standard professionale. In grandi progetti (Airbnb, Uber), la revisione del codice richiede una giustificazione per ogni unowned. Se la garanzia non è ovvia, usa weak. Un commento su unowned aiuta gli sviluppatori futuri a capire perché weak non è stato usato qui e quali condizioni potrebbero rompere la garanzia.

Domande Frequenti

Cosa succede quando si accede a un riferimento unowned dopo che l'oggetto è stato liberato?

Crash a runtime con EXC_BAD_ACCESS. Swift non verifica la validità di un riferimento unowned all'accesso — è semplicemente un puntatore “grezzo”. Se l'oggetto viene liberato, la memoria viene sovrascritta e accedervi termina fatalmente. Questa è un'eccezione non catturabile (non try-catch).

Si può usare unowned con i protocolli?

Sì, se il protocollo eredita da AnyObject. Unowned funziona con tutti i tipi riferimento: classi, protocolli AnyObject, oggetti Objective-C. I tipi valore (struct, enum) non supportano unowned perché non partecipano ad ARC.

Quando unowned è più sicuro di weak?

Quando la garanzia del ciclo di vita è assoluta e ovvia — unowned è più sicuro dal punto di vista del design: non richiede unwrap, non può essere nil e non maschera errori. Se un oggetto non può esistere senza un genitore, unowned lo rende un contratto esplicito, mentre weak offusca la garanzia.

C'è differenza di prestazioni tra unowned e weak?

Sì: unowned è più veloce perché non richiede accesso alla tabella weak a runtime per l'azzeramento. Nella maggior parte delle applicazioni la differenza è impercettibile, ma in scenari ad alto carico con milioni di accessi, unowned può essere 10–20% più veloce in lettura.

Come il refactoring influisce sulle garanzie di unowned?

Il refactoring è il pericolo principale per unowned. Modificare il ciclo di vita dell'oggetto (caching, operazioni asincrone, riutilizzo) può rompere la garanzia. Il compilatore non avviserà. Soluzione: migra a weak quando cambi architettura o aggiungi un commento di avvertimento.

Riepilogo

  • Unowned Reference — riferimento non possessivo senza azzeramento; non opzionale, non aumenta il retain count
  • Garanzia — richiede prova esplicita che l'oggetto viva almeno quanto il codice che lo riferisce
  • Sintassiunowned let o unowned var; può essere non opzionale e opzionale (Swift 5.0+)
  • Unowned vs Weak — unowned è più veloce e pulito, ma weak è più sicuro; weak è la scelta predefinita
  • Closure — unowned self solo per closure sincrone; quelle asincrone richiedono [weak self]
  • Documentazione — ogni unowned deve avere un commento che giustifichi la garanzia
  • Raccomandazione — in caso di dubbio, scegli weak; unowned è per contratti espliciti e documentati

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche