Vi sono due punti importanti nel modello di gestione degli errori di Swift 2: esaustività e resilienza. Insieme, si riducono alla tua do
/ catch
dichiarazione che deve cogliere ogni possibile errore, non solo quelli che sai di poter lanciare.
Si noti che non si dichiarano i tipi di errori che una funzione può generare, solo se si lancia affatto. È un tipo di problema zero-infinito: come qualcuno che definisce una funzione che gli altri (incluso il tuo sé futuro) possono usare, non devi fare in modo che ogni cliente della tua funzione si adatti ad ogni cambiamento nell'implementazione del tuo funzione, inclusi gli errori che può generare. Vuoi che il codice che chiama la tua funzione sia resistente a tale cambiamento.
Poiché la tua funzione non è in grado di dire che tipo di errori genera (o che potrebbe essere generato in futuro), i catch
blocchi che li rilevano non conoscono i tipi di errori che potrebbero essere generati. Quindi, oltre a gestire i tipi di errore che conosci, devi gestire quelli che non hai con catch
un'istruzione universale - in questo modo se la tua funzione cambia l'insieme di errori che genera in futuro, i chiamanti ne prenderanno comunque errori.
do {
let sandwich = try makeMeSandwich(kitchen)
print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
print("Not me error")
} catch SandwichError.DoItYourself {
print("do it error")
} catch let error {
print(error.localizedDescription)
}
Ma non fermiamoci qui. Pensa ancora a questa idea di resilienza. Nel modo in cui hai progettato il tuo sandwich, devi descrivere gli errori in ogni luogo in cui li usi. Ciò significa che ogni volta che cambi l'insieme dei casi di errore, devi cambiare ogni luogo che li utilizza ... non molto divertente.
L'idea alla base della definizione dei propri tipi di errore è quella di consentire di centralizzare cose del genere. Puoi definire un description
metodo per i tuoi errori:
extension SandwichError: CustomStringConvertible {
var description: String {
switch self {
case NotMe: return "Not me error"
case DoItYourself: return "Try sudo"
}
}
}
E poi il tuo codice di gestione degli errori può chiedere al tuo tipo di errore di descriverlo - ora ogni posto in cui gestisci gli errori può usare lo stesso codice e gestire anche possibili casi di errore futuri.
do {
let sandwich = try makeMeSandwich(kitchen)
print("i eat it \(sandwich)")
} catch let error as SandwichError {
print(error.description)
} catch {
print("i dunno")
}
Questo apre anche la strada a tipi di errore (o estensioni su di essi) per supportare altri modi di segnalazione degli errori - ad esempio, potresti avere un'estensione sul tuo tipo di errore che sa come presentare un UIAlertController
per segnalare l'errore a un utente iOS.