Storia della domanda:
L’optional chaining è stato introdotto in Swift per facilitare il lavoro con gli optional annidati, consentendo di scrivere codice compatto e sicuro senza controlli infiniti su nil. Questo è particolarmente utile quando si accede a proprietà e metodi di oggetti che potrebbero non esistere.
Problema:
Lavorando con optional chaining, è facile fraintendere quale risultato si avrà se uno degli oggetti nella catena è nil, o se non si gestisce correttamente il valore restituito, si possono verificare errori di runtime o comportamenti inattesi.
Soluzione:
L’optional chaining è un meccanismo che consente di accedere in modo sicuro alle proprietà, ai metodi e ai subscript annidati di oggetti che possono essere nil. Se uno qualsiasi degli elementi nella catena è nil, l’intera espressione restituirà nil, senza generare errori.
Esempio di codice:
class Address { var city: String? } class User { var address: Address? } let user: User? = User() user?.address?.city = "Mosca" if let city = user?.address?.city { print(city) } else { print("Città non trovata") }
Caratteristiche chiave:
Si verifica un errore di runtime se si tenta di chiamare un metodo o ottenere una proprietà tramite optional chaining se l'oggetto è nil?
No, non si verifica un errore di runtime. L'intera espressione tramite optional chaining restituisce nil, l'esecuzione si interrompe senza errore.
Esempio di codice:
let email: String? = nil let lowercased = email?.lowercased() // lowercased sarà nil, non verrà generato un errore
L'assegnazione tramite optional chaining verrà eseguita se l'oggetto intermedio è assente?
No, se l'oggetto o la proprietà intermedia sono nil, l'assegnazione non avrà alcun effetto e non modificherà la memoria.
Esempio di codice:
var user: User? = nil user?.address?.city = "Kazan" // non succederà nulla, user è nil
Il risultato dell'optional chaining può essere non optional?
No, il risultato di qualsiasi espressione tramite optional chaining sarà sempre un optional, anche se la proprietà originale non è opzionale.
Esempio di codice:
class Test { var number: Int = 10 } let t: Test? = nil let value = t?.number // value: Int? (optional)
Nel codice si accede a user?.address?.city senza successiva verifica della presenza della città e si stampa immediatamente city!. Si verifica un crash se uno qualsiasi dei link è nil.
Pro:
Contro:
Nel codice si utilizza if let o guard let per controllare user?.address?.city e si lavora solo dopo aver verificato il valore.
Pro:
Contro: