Do-Catch ist ein Sprachkonstrukt in Swift zur Fehlerbehandlung, das Ausnahmen abfängt, die über throw ausgelöst wurden, und den entsprechenden Codeblock ausführt. Im Gegensatz zu traditionellem try-catch in anderen Sprachen erfordert Swift eine explizite Markierung von Funktionen, die einen Fehler auslösen können, mit dem Modifikator throws. Laut Swift.org, 2026 ist Do-Catch der primäre Fehlerbehandlungsmechanismus in Swift und bietet Typsicherheit.
Kernpunkte
Do-Catch ist ein Konstrukt in Swift, das aus einem do-Block, in dem Code ausgeführt wird, der einen Fehler auslösen kann, und einem oder mehreren catch-Blöcken besteht, die diesen Fehler behandeln. Der do-Block enthält Aufrufe von throwing-Funktionen, die mit try markiert sind, und catch-Blöcke gleichen den Fehler nach Typ ab.
Swift implementiert ein Modell der strukturierten Fehlerbehandlung, das sich von Ausnahmen in Objective-C unterscheidet. Hier ist ein Fehler kein Exception mit Stack-Entwicklung, sondern ein Wert, der dem Error-Protokoll entspricht. Das Auslösen eines Fehlers über throw überträgt die Kontrolle an den nächsten catch-Block ohne den Overhead der Stack-Entwicklung.
Ein Schlüsselmerkmal von Swift ist die explizite Behandlung. Der Compiler erlaubt nicht, eine throwing-Funktion ohne try, do-catch oder einen alternativen Mechanismus (try?, try!) aufzurufen. Dies schließt Situationen aus, in denen ein Fehler unbemerkt bleibt.
Im Zentrum der Fehlerbehandlung in Swift steht das Error-Protokoll. Jeder Typ, der diesem Protokoll entspricht, kann über throw ausgelöst werden. Fehler werden typischerweise als Enum definiert, das Error entspricht.
Error ist ein leeres (Marker-)Protokoll. Es erfordert keine Methodenimplementierung, nur Konformität. Der Swift-Compiler verwendet Error für die statische Überprüfung: Eine Funktion mit throws kann nur einen Wert auslösen, der Error entspricht.
Eine mit throws markierte Funktion muss mit try aufgerufen werden. Wenn innerhalb einer solchen Funktion ein throw auftritt, wird die Kontrolle an den aufrufenden do-catch übertragen. Wenn der Fehler nirgendwo in der Aufrufkette behandelt wird, propagiert er auf die nächsthöhere Ebene.
enum FileError: Error {
case notFound
case permissionDenied
case corrupted(String)
}
func readFile(path: String) throws -> String {
guard FileManager.default.fileExists(atPath: path) else {
throw FileError.notFound
}
return try String(contentsOfFile: path)
}
rethrows ist ein Modifikator für Funktionen, die einen throwing-Closure als Parameter akzeptieren. Wenn der übergebene Closure keinen Fehler auslöst, kann die rethrows-Funktion ohne try aufgerufen werden. Dies ermöglicht das Schreiben generischer Funktionen höherer Ordnung, die sowohl mit throwing- als auch mit nicht-throwing-Closures kompatibel sind.
Swift unterstützt mehrere catch-Blöcke mit typbasierter Fehlerzuordnung. Dies ähnelt when in Kotlin oder einem typorientierten switch: Der erste passende catch wird ausgeführt, die restlichen werden übersprungen.
Jeder catch-Block kann ein Muster enthalten, das einem bestimmten Fehlertyp entspricht. Swift überprüft die Blöcke der Reihe nach, daher sollten spezifischere Typen vor allgemeineren kommen. Wenn kein Muster passt, wird der catch-Block ohne Muster ausgeführt.
Die Typsicherheit von Do-Catch ermöglicht es, jeden Fehler separat zu behandeln oder mehrere Typen in einem Block durch Komma-getrennten Mustervergleich zu kombinieren. Dies beseitigt umständliche if-else-Ketten, die für Objective-C typisch sind, wo die Fehleranalyse über Rückgabecodes oder NSError mit Domain- und Code-Prüfung erfolgte.
Swift unterstützt auch catch where — Zuordnung mit zusätzlicher Bedingung. Zum Beispiel kann man Fehler nach einem bestimmten Code oder Text filtern: catch URLError where error.code == .notConnectedToInternet. Dies reduziert die Anzahl der catch-Blöcke bei gleichbleibender Präzision.
Zum Debuggen von throwing-Funktionen bietet Swift eine Unterscheidung zwischen Fehlern und Ausnahmen. Ein Swift-Fehler ist ein Rückgabewert, der keine Stack-Entwicklung erfordert. Objective-C-Ausnahmen (@try/@catch) arbeiten auf Runtime-Ebene und werden nur für fatale Fehler verwendet. Do-Catch behandelt Fehler, nicht Ausnahmen, was es vorhersagbar und leistungsfähig macht.
Bei der Entwicklung von Bibliotheken und SDKs ist es wichtig zu bedenken, dass throwing-Funktionen Teil des öffentlichen Vertrags sind. Der Fehlertyp ist nicht in der Signatur spezifiziert, daher dokumentieren Sie, welche Fehler eine Funktion auslösen kann, in Kommentaren oder über Result-ähnliche Enums. Dies hilft API-Benutzern, korrekte catch-Blöcke zu schreiben, ohne in die Implementierung schauen zu müssen.
Im Kontext der asynchronen Programmierung löst Do-Catch mit async/await das Problem des Callback-Hell. Früher erforderte die Fehlerbehandlung in asynchronem Code in Swift verschachtelte Closures mit Error?-Prüfung in Completion-Handlern. Mit async/await und Do-Catch sieht asynchroner throwing-Code wie synchroner Code aus, was das Lesen und Warten komplexer Anforderungsketten mit Fehlerbehandlung bei jedem Schritt vereinfacht.
do {
let content = try readFile(path: "/data/config.json")
process(content)
} catch FileError.notFound {
createDefaultConfig()
} catch FileError.permissionDenied {
requestAccess()
} catch FileError.corrupted(let detail) {
logCorruption(detail)
} catch {
print("Unbekannter Fehler: \(error)")
}
Swift bietet drei Möglichkeiten, throwing-Funktionen aufzurufen: try, try? und try!. Jede Option löst eine bestimmte Aufgabe und hat ihre Grenzen.
try wird innerhalb eines do-Blocks verwendet, und der Fehler wird in catch behandelt. Dies ist die primäre Art, throwing-Funktionen aufzurufen. Der Compiler verlangt, dass try sich in einem Kontext befindet, in dem der Fehler abgefangen werden kann.
try? wandelt das Ergebnis einer throwing-Funktion in ein Optional um. Wenn die Funktion einen Fehler auslöst, gibt try? nil zurück, andernfalls ein Optional mit dem erfolgreichen Wert. Nützlich für Aufrufe, bei denen der Fehler ignoriert werden kann, aber ein Erfolgsindikator benötigt wird.
try! unterdrückt die Fehlerbehandlung. Wenn die throwing-Funktion einen Fehler auslöst, wird die App mit einem Laufzeitfehler beendet. Verwenden Sie try! nur, wenn Sie absolut sicher sind, dass der Fehler unmöglich ist — zum Beispiel beim Laden einer gebündelten Ressource.
// try? — Fehler ignorieren, nil bei Fehlschlag erhalten
if let data = try? Data(contentsOf: url) {
processData(data)
}
// try! — nur wenn der Fehler garantiert unmöglich ist
let bundled = try! String(contentsOfFile: "Assets/default.txt")
// try — Standardoption in do-catch
do {
let result = try performNetworkRequest()
updateUI(result)
} catch {
showError(error)
}
Do-Catch wird in der iOS-Entwicklung aktiv für die Arbeit mit System-APIs verwendet. Betrachten wir typische Szenarien: Arbeit mit dem Dateisystem, Core Data und Netzwerkanfragen.
Viele Methoden von FileManager sind throwing. Do-Catch ermöglicht die korrekte Behandlung von fehlenden Dateien, Ressourcenbelegung oder unzureichenden Berechtigungen.
Das Parsen von JSON über JSONDecoder ist eine throwing-Operation. Do-Catch fängt Dekodierungsfehler und Netzwerkausfälle separat ab und liefert dem Benutzer eine genaue Fehlermeldung.
struct User: Codable {
let id: Int
let name: String
}
func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
// Aufruf mit Behandlung
do {
let user = try await fetchUser(id: 42)
showUser(user)
} catch let error as URLError {
showNetworkAlert(error)
} catch let error as DecodingError {
showParseError(error)
} catch {
showGenericError(error)
}
Entwickler, insbesondere solche, die von anderen Sprachen kommen, machen oft charakteristische Fehler bei der Verwendung von Do-Catch. Betrachten wir die häufigsten.
Häufig gestellte Fragen
In Swift ist ein Fehler ein Wert, der dem Error-Protokoll entspricht, keine Ausnahme mit Stack-Entwicklung. Throwing-Funktionen müssen explizit mit throws markiert werden, und der Compiler verlangt try beim Aufruf — dies schließt unbehandelte Fehler zur Kompilierungszeit aus.
Ja, async-Funktionen können auch throws sein, und do-catch funktioniert mit ihnen. Der Aufruf einer asynchronen throwing-Funktion erfordert try await innerhalb eines do-Blocks. Dies ist die Standardmethode zur Fehlerbehandlung in asynchronem Swift-Code.
Es gibt Alternativen: try? wandelt den Fehler in nil um, try! verursacht bei Fehler einen Crash, und rethrows ermöglicht die Weitergabe eines Fehlers aus einem Closure. Do-catch bleibt die primäre Methode der expliziten Behandlung.
Swift typisiert die ausgelösten Fehler nicht — jede throwing-Funktion kann jeden Typ auslösen, der Error entspricht. Trennen Sie die Behandlung durch Zuordnung in catch nach spezifischen Fehlertypen.
Ja, das ist eine bewährte Praxis. Definieren Sie AppError als Enum, das Error entspricht, und konvertieren Sie Systemfehler in Domänenfehler. Dies vereinheitlicht die Behandlung und isoliert die Anwendungsschicht von Systemdetails.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch