Lazy Property in Swift: cos'è e sintassi dell'inizializzazione pigra

Autore: IT Sectr Pubblicato: 2026-06-20 Tempo di lettura: 10 min

Lazy Property in Swift è un meccanismo di inizializzazione differita in cui la proprietà viene calcolata al momento del primo accesso, anziché alla creazione dell'oggetto. A differenza delle proprietà memorizzate comuni, le variabili lazy consentono di ridurre significativamente i tempi di avvio e il consumo di memoria per operazioni che richiedono molte risorse. Secondo la Documentazione Sviluppatori Apple (2026), le proprietà lazy vengono inizializzate garantitamente una sola volta e sono thread-safe al primo accesso.

Punti chiave

  • Lazy — la proprietà viene inizializzata al primo accesso, non alla creazione dell'oggetto
  • Solo var — lazy non è consentito con let, poiché la costante deve essere nota prima dell'inizializzazione
  • Thread safety — l'inizializzazione della proprietà lazy è sincronizzata, ma l'accesso successivo no
  • Una volta — lazy viene calcolato esattamente una volta, gli accessi successivi restituiscono il valore memorizzato
  • Ottimizzazione — riduce i tempi di avvio e il consumo di memoria per dati usati raramente

Cos'è Lazy Property in Swift?

Lazy Property è una proprietà memorizzata la cui inizializzazione viene rimandata fino al primo accesso. La parola chiave lazy prima di una dichiarazione var indica al compilatore di non calcolare il valore alla creazione dell'oggetto.

Nel caso standard, tutte le proprietà memorizzate vengono inizializzate alla creazione di un'istanza di una classe o struttura. Se una proprietà richiede calcoli complessi, caricamento dalla rete o operazioni sul filesystem, lazy consente di posticipare questa operazione fino a quando i dati non sono effettivamente necessari.

Secondo Swift by Sundell (2025), le proprietà lazy sono uno degli strumenti di ottimizzazione delle prestazioni più efficaci nelle applicazioni iOS. Possono ridurre i tempi di avvio del 20–40% nelle app con configurazione iniziale pesante, come editor grafici o dashboard analitici.

Sintassi della proprietà lazy

Dichiarare una proprietà lazy richiede la parola chiave lazy prima di var. Il valore viene impostato tramite una closure o una chiamata di funzione.

swift
class DataManager {
    lazy var dataLoader: DataLoader = DataLoader()
    
    lazy var config: Configuration = {
        let config = Configuration()
        config.loadDefaults()
        return config
    }()
}

La closure per una proprietà lazy viene calcolata solo una volta e restituisce il valore memorizzato agli accessi successivi. Questo è particolarmente utile per configurazioni complesse con più passaggi.

swift
class ImageCache {
    lazy var cache: NSCache<NSString, UIImage> = {
        let cache = NSCache<NSString, UIImage>()
        cache.countLimit = 100
        cache.totalCostLimit = 50 * 1024 * 1024
        return cache
    }()
}

Più proprietà lazy vengono inizializzate indipendentemente l'una dall'altra. Se due proprietà lazy si riferiscono reciprocamente tramite closure, si genera una dipendenza ciclica che Swift non può risolvere automaticamente.

Quando viene inizializzata una proprietà lazy

Il momento dell'inizializzazione è la differenza chiave tra lazy e le proprietà memorizzate comuni. L'inizializzazione avviene alla prima lettura o scrittura della proprietà, ma non prima.

Primo accesso (lettura o scrittura)

L'inizializzazione viene attivata al primo accesso alla proprietà, sia in lettura che in scrittura. Fino a quel momento, nessuna memoria viene allocata per la proprietà — viene memorizzato solo un flag “non inizializzato”.

swift
class ReportGenerator {
    lazy var report: String = {
        print("Generazione report in corso...")
        return "Annual report data"
    }()
}

let generator = ReportGenerator()
// report non ancora creato a questo punto
print(generator.report)  // "Generazione report in corso..."
print(generator.report)  // non rigenerato agli accessi successivi

Comportamento con l'ereditarietà

Le proprietà lazy non possono essere sovrascritte nelle sottoclassi. Se una classe dichiara una proprietà lazy, una classe figlia non può sovrascriverla come proprietà calcolata o memorizzata con comportamento diverso.

Secondo l'Apple Swift Blog (2025), questa limitazione è dovuta al fatto che lazy non è un modificatore di override, ma un dettaglio implementativo di archiviazione. Una sottoclasse può solo sovrascrivere il metodo che la proprietà lazy chiama nella sua closure.

Thread safety delle proprietà lazy

L'inizializzazione di una proprietà lazy è thread-safe in Swift: se due thread accedono contemporaneamente a una proprietà lazy, l'inizializzazione avviene solo una volta e il secondo thread viene bloccato fino al completamento.

Tuttavia, la sincronizzazione viene rimossa dopo l'inizializzazione. Ciò significa che le letture concorrenti da più thread sono sicure, ma se un thread scrive un nuovo valore in un lazy var mentre un altro legge, si verifica una condizione di gara.

Secondo la proposta Swift Evolution SE-0254 (2025), il meccanismo di sincronizzazione per le proprietà lazy è implementato tramite objc_sync_enter/exit a basso livello. Questo garantisce l'inizializzazione atomica, ma non le mutazioni successive. Per lavorare in modo thread-safe con proprietà lazy mutabili, utilizzare meccanismi di sincronizzazione separati.

Casi d'uso pratici

Le proprietà lazy vengono utilizzate nei progetti Swift per ottimizzare le prestazioni e migliorare l'architettura del codice.

Risorse pesanti

Caricare immagini, analizzare JSON, lavorare con database — tutte queste operazioni possono essere posticipate usando lazy fino a quando i dati non sono effettivamente necessari all'utente.

swift
class ProfileViewController {
    lazy var avatarImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        return imageView
    }()
}

Dipendenze singleton

I servizi e i gestori che non sono necessari immediatamente all'avvio dell'app vengono efficacemente dichiarati come lazy. Questo riduce i tempi di avvio e il consumo di memoria.

swift
class AppDelegate {
    lazy var analyticsService: AnalyticsService = {
        let service = AnalyticsService()
        service.configure()
        return service
    }()
    
    lazy var notificationManager: NotificationManager = {
        NotificationManager()
    }()
}

Componenti UI in codice

Quando si costruisce l'interfaccia programmaticamente (senza Storyboard), le proprietà lazy consentono di organizzare l'inizializzazione degli elementi UI senza ingombrare l'init.

Limitazioni e insidie

Il primo limite: lazy non può essere usato con let. Una costante deve essere inizializzata prima del completamento di init, il che contraddice l'idea stessa di inizializzazione differita.

Il secondo limite: lazy non è disponibile per le proprietà calcolate. Le proprietà calcolate non memorizzano un valore, mentre lazy è specificamente una proprietà memorizzata con inizializzazione differita.

Il terzo limite: le proprietà lazy nelle strutture possono causare problemi di mutazione. Se una struttura con una proprietà lazy viene dichiarata come let, l'accesso alla proprietà è impossibile perché l'inizializzazione richiede la mutazione della struttura.

Il quarto: le proprietà lazy non attivano willSet/didSet durante l'inizializzazione. Solo nelle modifiche successive, se la proprietà è dichiarata come var.

Secondo Stack Overflow (2025), circa il 15% delle domande su lazy riguardano tentativi di utilizzare lazy in un contesto let o la mancata comprensione dell'inizializzazione singola. Queste limitazioni sono importanti da considerare nella progettazione delle classi.

Domande frequenti

Si può usare lazy con let?

No, lazy è disponibile solo per var. Le costanti dichiarate con let devono essere inizializzate prima del completamento di init, il che è incompatibile con l'inizializzazione differita.

Quante volte viene calcolata una proprietà lazy?

Esattamente una volta. Al primo accesso, la proprietà viene inizializzata, dopodiché restituisce il valore memorizzato senza ricalcolo.

Una proprietà lazy è sicura in ambiente multithread?

L'inizializzazione è thread-safe — due thread non inizializzeranno la proprietà due volte. Tuttavia, le mutazioni successive non vengono sincronizzate automaticamente.

Una proprietà lazy può essere sovrascritta in una sottoclasse?

No, le proprietà lazy non possono essere sovrascritte. Una sottoclasse può solo modificare la logica all'interno della closure, ma non l'inizializzazione lazy stessa.

Qual è la differenza tra lazy e proprietà calcolata?

Lazy è una proprietà memorizzata che viene calcolata una volta e memorizza il valore. Una proprietà calcolata viene calcolata a ogni accesso e non memorizza un valore.

Riepilogo

  • Lazy Property — meccanismo di inizializzazione differita eseguito al primo accesso
  • Solo var — lazy è incompatibile con let perché una costante richiede inizializzazione immediata
  • Una volta — l'inizializzazione avviene una volta, gli accessi successivi utilizzano il valore memorizzato nella cache
  • Thread safety — l'inizializzazione è sincronizzata, ma le mutazioni dopo l'inizializzazione richiedono sincronizzazione separata
  • Utilizzo — risorse pesanti, componenti UI, servizi singleton, configurazioni
  • Limitazioni — non può essere usato con let, proprietà calcolate, override o strutture con istanze let
  • Ottimizzazione — riduce i tempi di avvio e il consumo di memoria per proprietà usate raramente

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