Fehlerbehandlung in Swift: try/catch, throws und do-catch Blöcke

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Fehlerbehandlung in Swift: try/catch und mehr



Die Entwicklung für iOS und macOS erfordert eine zuverlässige Fehlerverwaltung. Swift bietet einen leistungsstarken und eleganten Mechanismus zur Fehlerbehandlung, der auf den Schlüsselwörtern throws, try, catch und do basiert. In diesem Artikel werden wir uns ansehen, wie man Fehler richtig behandelt, lesbaren Code schreibt und häufige Fallstricke vermeidet.



1. Grundlagen: Das Error-Protokoll und das Schlüsselwort throws



Jeder Fehler in Swift muss dem Error-Protokoll entsprechen. Üblicherweise verwendet man dafür Aufzählungen (enum):



enum NetworkError: Error {    case badURL    case noData    case decodingFailed(String)}


Eine Funktion, die einen Fehler werfen kann, wird mit dem Schlüsselwort throws markiert:



func fetchUser(from urlString: String) throws -> User {    guard let url = URL(string: urlString) else {        throw NetworkError.badURL    }    // ... Logik der Anfrage}


Beim Aufruf einer solchen Funktion zwingt Sie der Compiler nun, den möglichen Fehler zu behandeln.



2. Die do-catch-Konstruktion: Abfangen von Fehlern



Die gebräuchlichste Methode zur Fehlerbehandlung ist der do-catch-Block. Sie platzieren den potenziell gefährlichen Code in do und behandeln den Fehler im catch-Block:



do {    let user = try fetchUser(from: "https://api.example.com/user")    print("User loaded: \\(user.name)")} catch NetworkError.badURL {    print("Ungültige URL")} catch NetworkError.noData {    print("Server hat keine Daten zurückgegeben")} catch NetworkError.decodingFailed(let message) {    print("Dekodierungsfehler: \\(message)")} catch {    print("Unbekannter Fehler: \\(error.localizedDescription)")}


Wichtig: Der letzte catch-Block ohne spezifischen Typ fängt alle verbleibenden Fehler – Sie sollten ihn immer hinzufügen.



2.1. Pattern Matching in catch



Sie können komplexere Bedingungen verwenden:



do {    let result = try riskyOperation()} catch let error as NetworkError where error == .badURL {    print("Problem mit der URL")} catch {    print(error)}


3. Alternativen: try? und try!



Nicht immer ist eine vollständige Fehlerbehandlung nötig. Swift bietet zwei vereinfachte Ansätze:



3.1. try? — Optionaler Wert



Wenn der Fehler nicht kritisch ist, kann man das Ergebnis in ein Optional umwandeln. Bei einem Fehler gibt die Funktion nil zurück:



let user = try? fetchUser(from: "https://example.com/user")// user hat den Typ User? — nil bei Fehler


Ideal für Situationen, in denen der Fehler einfach ignoriert werden kann (z.B. Laden eines Avatars).



3.2. try! — Erzwungene Ausführung



Verwenden Sie try! nur, wenn Sie absolut sicher sind, dass kein Fehler auftritt. Sonst führt es zum Absturz der App:



let user = try! fetchUser(from: "https://valid-url.com/user")// Wenn die URL ungültig ist — stürzt die App ab


Wenden Sie try! in Tests oder in Situationen an, in denen ein Fehler aufgrund der Programmlogik unmöglich ist.



4. Fortgeschrittene Techniken: rethrows und deferred



4.1. rethrows für Funktionen höherer Ordnung



Wenn Ihre Funktion einen Closure akzeptiert, der einen Fehler werfen kann, verwenden Sie rethrows. Dies erlaubt es, die eigene Funktion nicht als throws zu markieren, wenn der Closure keinen Fehler wirft:



func process(_ closure: () throws -> Void) rethrows {    try closure()}

// Aufruf ohne throws-Closure — erfordert kein do-catchprocess { print("Keine Fehler") }

// Aufruf mit throws-Closure — erfordert Fehlerbehandlungtry process { throw NetworkError.noData }


4.2. deferred: Garantierte Bereinigung



Der defer-Block wird bei jedem Beenden der Funktion ausgeführt (Erfolg oder Fehler). Ideal zum Schließen von Dateien oder Freigeben von Res

Blogs

Buchempfehlungen