Do-Catch — konstrukcja języka Swift do obsługi błędów, która przechwytuje wyjątki zgłoszone przez throw i wykonuje odpowiedni blok kodu. W przeciwieństwie do tradycyjnych try-catch w innych językach, Swift wymaga jawnego oznaczenia funkcji, które mogą zgłosić błąd, modyfikatorem throws. Według Swift.org, 2026, Do-Catch to podstawowy mechanizm obsługi błędów w Swift, zapewniający bezpieczeństwo na poziomie typów.
Najważniejsze
Do-Catch — to konstrukcja w Swift składająca się z bloku do, wewnątrz którego wykonywany jest kod mogący zgłosić błąd, oraz jednego lub więcej bloków catch, obsługujących ten błąd. Blok do zawiera wywołania funkcji throwing oznaczone try, a bloki catch dopasowują błąd według typu.
Swift implementuje model strukturalnej obsługi błędów, różniący się od wyjątków w Objective-C. Tutaj błąd to nie exception z rozwijaniem stosu, ale wartość zgodna z protokołem Error. Zgłoszenie błędu przez throw przekazuje sterowanie do najbliższego bloku catch bez narzutu na rozwijanie stosu.
Kluczowa cecha Swift — jawność obsługi. Kompilator nie pozwala wywołać funkcji throwing bez try, do-catch lub alternatywnego mechanizmu (try?, try!). Eliminuje to sytuacje, w których błąd pozostaje niezauważony.
Podstawą obsługi błędów w Swift jest protokół Error. Każdy typ zgodny z tym protokołem może być zgłoszony przez throw. Zazwyczaj błędy definiuje się jako enum z potwierdzeniem Error.
Error — pusty protokół (znacznikowy). Nie wymaga implementacji metod, tylko potwierdzenia zgodności. Kompilator Swift używa Error do statycznego sprawdzania: funkcja z throws może zgłosić tylko wartość zgodną z Error.
Funkcja oznaczona throws musi być wywoływana z try. Jeśli wewnątrz takiej funkcji nastąpi throw, sterowanie przekazywane jest do wywołującego do-catch. Jeśli błąd nie zostanie obsłużony nigdzie w łańcuchu wywołań, jest propagowany na wyższy poziom.
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 — modyfikator dla funkcji, które przyjmują throwing-zamknięcie jako parametr. Jeśli przekazane zamknięcie nie zgłasza błędu, funkcję rethrows można wywołać bez try. Pozwala to pisać ogólne funkcje wyższego rzędu, kompatybilne z throwing i non-throwing zamknięciami.
Swift obsługuje wielokrotne bloki catch z dopasowaniem według typu błędu. Przypomina to when w Kotlin lub switch według typu: pierwszy pasujący catch jest wykonywany, pozostałe są pomijane.
Każdy blok catch może zawierać wzorzec dopasowania do konkretnego typu błędu. Swift sprawdza bloki po kolei, więc bardziej specyficzne typy powinny znajdować się przed ogólnymi. Jeśli żaden wzorzec nie pasuje, wykonywany jest blok catch bez wzorca.
Bezpieczeństwo typów Do-Catch pozwala obsługiwać każdy błąd osobno lub łączyć wiele typów w jednym bloku przez przecinek w pattern-matching. Eliminuje to rozwlekłe łańcuchy if-else charakterystyczne dla Objective-C, gdzie analiza błędu odbywała się przez kod powrotu lub NSError z sprawdzaniem domain i code.
Swift obsługuje również catch where — dopasowanie z dodatkowym warunkiem. Można na przykład filtrować błędy według konkretnego kodu lub tekstu: catch URLError where error.code == .notConnectedToInternet. Zmniejsza to liczbę bloków catch przy zachowaniu precyzji obsługi.
Do debugowania funkcji throwing Swift udostępnia różnicę między błędami a wyjątkami. Błąd Swift — to zwracana wartość, która nie wymaga rozwijania stosu. Wyjątki Objective-C (@try/@catch) działają na poziomie runtime i są używane tylko do krytycznych awarii. Do-Catch obsługuje właśnie błędy, a nie wyjątki, co czyni go przewidywalnym i wydajnym.
Przy tworzeniu bibliotek i SDK ważne jest, aby pamiętać, że funkcje throwing są częścią publicznego kontraktu. Typ błędu nie jest określony w sygnaturze, dlatego dokumentuj, jakie błędy może zgłosić funkcja, w komentarzu lub przez enum podobny do Result. Pomaga to użytkownikom API pisać poprawne bloki catch bez zaglądania do implementacji.
W kontekście programowania asynchronicznego Do-Catch z async/await rozwiązuje problem callback hell. Wcześniej w Swift obsługa błędów w kodzie asynchronicznym wymagała zagnieżdżonych zamknięć ze sprawdzaniem Error? w completion handler. Dzięki async/await i Do-Catch asynchroniczny kod throwing wygląda jak synchroniczny, co upraszcza czytanie i utrzymanie złożonych łańcuchów zapytań z obsługą błędów na każdym kroku.
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("Nieznany błąd: \(error)")
}
Swift oferuje trzy warianty wywołania funkcji throwing: try, try? i try!. Każdy wariant rozwiązuje konkretne zadanie i ma swoje ograniczenia.
try jest używane wewnątrz bloku do, a błąd jest obsługiwany w catch. To podstawowy sposób wywoływania funkcji throwing. Kompilator wymaga, aby try znajdowało się w kontekście, w którym błąd może zostać przechwycony.
try? przekształca wynik funkcji throwing na Optional. Jeśli funkcja zgłosi błąd, try? zwraca nil, w przeciwnym razie — Optional z wartością powodzenia. Przydatne w wywołaniach, gdzie błąd można zignorować, ale potrzebny jest wskaźnik sukcesu.
try! pomija obsługę błędów. Jeśli funkcja throwing zgłosi błąd, aplikacja kończy się błędem runtime. Używaj try! tylko gdy jesteś absolutnie pewien, że błąd jest niemożliwy — na przykład przy ładowaniu wbudowanego zasobu.
// try? — ignorujemy błąd, otrzymujemy nil przy awarii
if let data = try? Data(contentsOf: url) {
processData(data)
}
// try! — tylko jeśli błąd jest gwarantowanie niemożliwy
let bundled = try! String(contentsOfFile: "Assets/default.txt")
// try — standardowa opcja w do-catch
do {
let result = try performNetworkRequest()
updateUI(result)
} catch {
showError(error)
}
Do-Catch jest aktywnie używane w rozwoju iOS do pracy z systemowymi API. Rozważmy typowe scenariusze: praca z systemem plików, Core Data i zapytania sieciowe.
Wiele metod FileManager to throwing. Do-Catch pozwala poprawnie obsłużyć brak pliku, zajętość zasobu lub brak uprawnień.
Parsowanie JSON przez JSONDecoder — operacja throwing. Do-Catch przechwytuje błędy dekodowania i awarie sieciowe oddzielnie, dostarczając użytkownikowi dokładny tekst błędu.
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)
}
// Wywołanie z obsługą
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)
}
Deweloperzy, szczególnie przechodzący z innych języków, często popełniają charakterystyczne błędy podczas korzystania z Do-Catch. Rozważmy najczęstsze z nich.
Często zadawane pytania
W Swift błąd to wartość zgodna z protokołem Error, a nie exception z rozwijaniem stosu. Funkcje throwing muszą być jawnie oznaczone throws, a kompilator wymaga try przy wywołaniu — eliminuje to nieobsłużone błędy na etapie kompilacji.
Tak, async funkcje również mogą być throws i działa dla nich do-catch. Wywołanie async throwing funkcji wymaga try await wewnątrz bloku do. To standardowy sposób obsługi błędów w asynchronicznym kodzie Swift.
Są alternatywy: try? przekształca błąd w nil, try! powoduje crash przy błędzie, a rethrows pozwala propagować błąd z zamknięcia. Do-catch pozostaje podstawowym sposobem jawnej obsługi.
Swift nie typuje zgłaszanych błędów — każda funkcja throwing może zgłosić dowolny typ zgodny z Error. Rozdzielaj obsługę przez dopasowanie w catch do konkretnych typów błędów.
Tak, to najlepsza praktyka. Zdefiniuj AppError jako enum z potwierdzeniem Error i konwertuj błędy systemowe na domenowe. To ujednolica obsługę i izoluje warstwę aplikacji od szczegółów systemowych.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również