ProgrammazioneSviluppatore iOS

Quali sono le principali differenze tra le proprietà lazy in Swift? Quando è opportuno utilizzare lazy, quali sono le caratteristiche e le insidie nella loro inizializzazione e come evitare problemi comuni?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Le proprietà lazy in Swift vengono calcolate solo al primo accesso. Questo è spesso utilizzato per oggetti dispendiosi in termini di risorse (ad esempio, calcoli intensivi, caricamenti di rete), che non sono necessari immediatamente. Vengono dichiarate utilizzando la parola chiave lazy:

class DataFetcher { lazy var data: Data = self.loadData() func loadData() -> Data { /* … */ } }

Caratteristiche e dettagli:

  • Le proprietà lazy possono essere utilizzate solo per variabili (var), non per costanti (let).
  • All'interno delle strutture lazy non funzionano se la struttura stessa è immutabile.
  • Se impostato da un altro thread, non è thread-safe. È consigliabile evitare accessi simultanei alle proprietà lazy da thread diversi.
  • Quando si copia un oggetto di classe, il valore lazy viene memorizzato separatamente per ciascun istanza.

Domanda trabocchetto.

Domanda: "Viene creato un valore per la proprietà lazy durante l'inizializzazione dell'istanza della classe?"

Risposta: No, il valore viene calcolato solo al primo accesso alla proprietà, non durante l'inizializzazione.

class Expensive { init() { print("init") } } class Example { lazy var heavy = Expensive() } let foo = Example() // non stampa nulla _ = foo.heavy // ora "init"

Esempi di errori reali dovuti all'ignoranza delle sottigliezze della materia.


Storia

In un progetto su due piattaforme è stato utilizzato un array lazy (lazy var) per memorizzare la cache delle immagini. Con accessi simultanei da più thread si sono verificati race condition, hanno avvolto lazy var in mutex - ma hanno dimenticato di considerare lazy, portando al crash dell'applicazione.


Storia

Un giovane sviluppatore ha cercato di dichiarare lazy let per memorizzare un calcolo pesante. Il codice non si compilava, poiché lazy è consentito solo per var: ha dovuto rivedere l'architettura.


Storia

Lo sviluppatore ha dichiarato una proprietà lazy con cattura di self all'interno di una closure durante l'inizializzazione. Questo ha portato a un riferimento circolare: l'oggetto non è stato deinizializzato nemmeno dopo essere uscito da tutti gli schermi.