Das Swift 2-Fehlerbehandlungsmodell weist zwei wichtige Punkte auf: Vollständigkeit und Ausfallsicherheit. Zusammen laufen sie auf Ihre do
/ catch
-Anweisung hinaus und müssen jeden möglichen Fehler abfangen, nicht nur die, von denen Sie wissen, dass Sie sie werfen können.
Beachten Sie, dass Sie nicht deklarieren, welche Arten von Fehlern eine Funktion auslösen kann, sondern nur, ob sie überhaupt auslöst. Es ist ein Null-Eins-Unendlich-Problem: Als jemand, der eine Funktion definiert, die von anderen (einschließlich Ihres zukünftigen Selbst) verwendet werden soll, möchten Sie nicht jeden Client Ihrer Funktion dazu bringen müssen, sich an jede Änderung in der Implementierung Ihrer Funktion anzupassen Funktion, einschließlich der Fehler, die es auslösen kann. Sie möchten, dass Code, der Ihre Funktion aufruft, solchen Änderungen standhält.
Da Ihre Funktion nicht sagen kann, welche Art von Fehlern sie auslöst (oder in Zukunft auslösen könnte), catch
wissen die Blöcke, die sie abfangen, nicht, welche Arten von Fehlern sie auslösen könnte. Zusätzlich zu den Fehlertypen, die Sie kennen, müssen Sie diejenigen, die Sie nicht kennen, mit einer universellen catch
Anweisung behandeln. Wenn Ihre Funktion also die Menge der Fehler ändert, die sie in Zukunft auslöst, werden die Anrufer diese weiterhin abfangen Fehler.
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)
}
Aber lasst uns hier nicht aufhören. Denken Sie noch etwas über diese Resilienzidee nach. So wie Sie Ihr Sandwich entworfen haben, müssen Sie Fehler an jedem Ort beschreiben, an dem Sie sie verwenden. Das bedeutet, dass Sie jedes Mal, wenn Sie die Fehlerfälle ändern, jeden Ort ändern müssen, an dem sie verwendet werden ... nicht sehr lustig.
Die Idee hinter der Definition Ihrer eigenen Fehlertypen besteht darin, dass Sie solche Dinge zentralisieren können. Sie können eine description
Methode für Ihre Fehler definieren:
extension SandwichError: CustomStringConvertible {
var description: String {
switch self {
case NotMe: return "Not me error"
case DoItYourself: return "Try sudo"
}
}
}
Und dann kann Ihr Fehlerbehandlungscode Ihren Fehlertyp auffordern, sich selbst zu beschreiben - jetzt kann jeder Ort, an dem Sie Fehler behandeln, denselben Code verwenden und auch mögliche zukünftige Fehlerfälle behandeln.
do {
let sandwich = try makeMeSandwich(kitchen)
print("i eat it \(sandwich)")
} catch let error as SandwichError {
print(error.description)
} catch {
print("i dunno")
}
Dies ebnet auch den Weg für Fehlertypen (oder Erweiterungen auf ihnen), um andere Arten der Fehlermeldung zu unterstützen. Sie könnten beispielsweise eine Erweiterung für Ihren Fehlertyp haben, die weiß, wie eine UIAlertController
Fehlermeldung für einen iOS-Benutzer angezeigt wird.