Swift wspiera ścisły system zarządzania błędami przez protokół Error oraz konstrukcje throw, try, catch. Możesz zdefiniować własne typy błędów, dziedzicząc po Error:
enum NetworkError: Error { case noInternet case serverError(code: Int) case unknown }
Funkcje, które mogą wyrzucić błąd, są deklarowane z throws:
func fetchData() throws -> Data { // ... throw NetworkError.noInternet }
Błędy można przetwarzać za pomocą bloku do-catch:
do { let data = try fetchData() // Praca z danymi } catch NetworkError.noInternet { print("Brak internetu") } catch { print("Inny błąd: \(error)") }
Alternatywnym podejściem jest typ Result<T, Error>, który pozwala zwracać rezultat albo błąd bez potrzeby użycia try-catch:
func fetchData() -> Result<Data, NetworkError> { // ... return .failure(.noInternet) } let result = fetchData() switch result { case .success(let data): // OK case .failure(let err): // Przetwarzanie błędu }
Kiedy używać:
try/catch, jeśli błąd jest krytyczny i nie można go zignorować.Result, jeśli funkcja jest asynchroniczna lub gdy wygodniej jest przekazywać błąd „na zewnątrz” bez wyjątków.Pytanie: "Czy można wyrzucać i łapać błędy dowolnego typu, na przykład ciągi znaków lub liczby?"
Odpowiedź: Nie, w Swift można wyrzucać tylko typy, które odpowiadają protokołowi Error.
// Źle: throw "StringError" // Kompilator nie pozwoli na to // Dobrze: struct MyError: Error {} throw MyError()
Historia
W projekcie klienta REST API wyrzucał błąd jako ciąg znaków (throw "No data"). Kod kompilował się w JavaScript, ale po przetłumaczeniu na Swift wystąpił krytyczny błąd kompilacji.
Historia
Programista zwracał błąd przez opcjonalne wartości (return nil przy błędzie), a nie przez throw/Result. W rezultacie zabrakło szczegółów błędów, trudno było je prawidłowo przetwarzać — pojawiły się ciche błędy (Silent fails).
Historia
Analiza wykazała, że w kilku miejscach aplikacji te same błędy nie były zgrupowane w jeden typ Error. W efekcie aplikacje różnie przetwarzały podobne awarie, UI wyświetlał różne komunikaty dla jednego błędu — trudne do utrzymania i testowania.