Obsługa błędów to podstawowa umiejętność dewelopera mobilnego. Według HackerOne (2025), 62% naruszeń danych wynika z nieobsłużonych wyjątków. Prawidłowa obsługa błędów nie tylko zapobiega awariom, ale także chroni dane użytkowników. Przeanalizujmy podejścia dla iOS, Androida i React Native.
Najważniejsze punkty
Obsługa błędów w Swifcie opiera się na czterech kluczowych mechanizmach: do-catch, throws, guard let i if-let. W przeciwieństwie do wielu języków, Swift nie pozwala na nieprzechwycone wyjątki — każdy błąd musi być jawnie obsłużony lub zadeklarowany przez throws. Obsługa błędów to krytyczna umiejętność w rozwoju mobilnym, bezpośrednio wpływająca na stabilność aplikacji.
do-catch to standardowy blok do wywoływania funkcji oznaczonych throws. Wewnątrz do funkcja jest wywoływana z try, a jeśli zgłosi błąd, sterowanie przechodzi do catch. Różne typy błędów można obsługiwać przez pattern matching. Jeśli błąd nie zostanie obsłużony, propaguje się w górę stosu (Error Propagation). Do skutecznej obsługi błędów w iOS używaj do-catch jako głównego mechanizmu.
Throw jest deklarowany w sygnaturze funkcji: func fetchData() throws -> Data. Oznacza to, że kod wywołujący musi obsłużyć błąd przez try, try? lub try!. try? konwertuje błąd na nil, try! powoduje awarię przy błędzie (używaj tylko jeśli jesteś pewien sukcesu). Obsługa błędów przez throw to obowiązkowa praktyka w Swifcie.
Guard let to konstrukcja do wczesnego wyjścia z funkcji, jeśli wartość to nil. W przeciwieństwie do if-let, guard let wymaga wyjścia (return, throw, break) w gałęzi else. To sprawia, że kod jest bardziej płaski i czytelny — bez zagnieżdżonych bloków if. Jeśli optional nie może być nullem — użyj force unwrap (!), tylko gdy jesteś absolutnie pewien. W aplikacji mobilnej guard let pomaga uniknąć awarii podczas obsługi wartości opcjonalnych.
Optional Chaining (user?.address?.city) i nil-coalescing (??) to cukier składniowy do pracy z optionalami bez rozpakowywania. W IT Sectr używamy guard let do walidacji parametrów wejściowych API i wymagamy od zespołu unikania force unwrap bez jawnego komentarza. Procedura obsługi błędów na każdym poziomie chroni przed nieoczekiwanymi awariami.
Kotlin to główny język do rozwoju Androida. Dziedziczy try-catch z Javy, ale dodaje bezpieczniejsze alternatywy: operator elvis, require, check i sealed class. Obsługa błędów w Kotlinie opiera się na kombinacji tych mechanizmów. W przeciwieństwie do Swifta, Kotlin nie wymaga obsługi wyjątków kontrolowanych (wszystkie wyjątki są unchecked). Do obsługi błędów w aplikacjach mobilnych na Androida używaj sealed class jako głównego wzorca.
Try-catch w Kotlinie działa jako wyrażenie — zwraca wartość. val result = try { fetchData() } catch (e: Exception) { fallbackValue }. To skraca kod. Operator Elvis (?:) to analog nil-coalescing dla typów nullable: val name = user?.name ?: "Guest". Do obsługi błędów w aplikacjach mobilnych try-catch jako wyrażenie to najbardziej zwięzłe podejście.
Sealed class to potężne narzędzie do modelowania stanów sukcesu i błędu. sealed class NetworkResult { data class Success(val data: T) : NetworkResult(); data class Error(val message: String) : NetworkResult() }. Użyta w wyrażeniu when, kompilator sprawdza kompletność gałęzi. Obsługa błędów przez sealed class gwarantuje, że żaden stan nie pozostanie nieobsłużony.
// Sealed class + try-catch — typowy wzorzec dla Androida
sealed class NetworkResult<out T> {
data class Success<out T>(val data: T) : NetworkResult<T>()
data class Error(val message: String) : NetworkResult<Nothing>()
}
fun fetchUser(id: String): NetworkResult<User> {
return try {
NetworkResult.Success(api.getUser(id))
} catch (e: Exception) {
NetworkResult.Error("Failed: ${e.message}")
}
}
W przykładzie sealed class NetworkResult modeluje dwa stany: sukces z danymi i błąd z komunikatem. Funkcja fetchUser zwraca wynik w każdym przypadku, a kod wywołujący obsługuje obie gałęzie przez when. Eliminuje to możliwość nieobsłużonego błędu. Obsługa błędów przez sealed class to standard rozwoju Androida w IT Sectr.
Result to wbudowany typ Kotlina do reprezentowania wyniku operacji, która może się nie powieść. Wymusza obsługę sukcesu i porażki przez fold, getOrThrow lub map. Result jest przydatny w łańcuchach asynchronicznych (coroutines). Obsługa błędów za pomocą Result to standard rozwoju mobilnego w Kotlinie.
Either to typ funkcyjny z biblioteki Arrow, który pozwala zwrócić wartość jednego z dwóch typów (Left — błąd, Right — sukces). W przeciwieństwie do Result, Either może zawierać dowolny typ błędu zdefiniowany przez użytkownika. Dla prostych projektów wystarczy wbudowany Result, dla złożonych — użyj Either z Arrow. Wybór narzędzia do obsługi błędów zależy od złożoności projektu.
Propagacja błędów to mechanizm, w którym błąd propaguje się w górę stosu wywołań, aż zostanie obsłużony. W Kotlinie dzieje się to domyślnie (wyjątki unchecked). W Swifcie dotyczy to tylko funkcji oznaczonych throws. W Result i Either błędy nie propagują się — pozostają w typie i musisz je obsłużyć. To sprawia, że obsługa błędów w aplikacjach mobilnych jest bezpieczniejsza.
| Parametr | iOS (Swift) | Android (Kotlin) |
|---|---|---|
| Podstawowy mechanizm | do-catch + throws | try-catch (expression) |
| Optional/Nullable | guard let, if-let, ?? | ?. let, elvis (?:) |
| Podejście funkcyjne | Result (Swift 5+) | Result, Either (Arrow) |
| Modelowanie błędów | Enum: Error | Sealed class |
| Kontrolowane wyjątki | Tak (throws) | Nie (wszystkie unchecked) |
| Non-fatal | os_log, Crashlytics | Timber, Crashlytics |
Tabela pokazuje kluczowe różnice. iOS wymaga jawnej deklaracji błędów (throws), co czyni kod bezpieczniejszym, ale bardziej rozwlekłym. Android polega na dyscyplinie dewelopera. W IT Sectr używamy sealed class dla Androida i throws dla iOS — to najlepsza praktyka obu platform dla obsługi błędów w aplikacjach mobilnych.
Crash reporting to system zbierania i analizy awarii aplikacji. Crash reporting to nieodłączna część obsługi błędów w produkcji. Bez niego dowiadujesz się o problemach od użytkowników, co jest nie do przyjęcia dla produkcji. Dwa główne narzędzia: Firebase Crashlytics (bezpłatne) i Sentry (bezpłatne do podstawowego użytku). Do obsługi błędów w aplikacjach mobilnych zawsze wdrażaj crash reporting od pierwszej wersji.
Crashlytics jest częścią Firebase. Automatycznie zbiera awarie, grupuje je według stosu wywołań i pokazuje liczbę dotkniętych użytkowników. Obsługuje rejestrowanie błędów niekrytycznych przez recordException(). Integracja: dodaj SDK do build.gradle (Android) lub Podfile (iOS). Crashlytics to najlepsze darmowe narzędzie do obsługi błędów na starcie projektu.
Sentry to wieloplatformowy system monitorowania błędów. W przeciwieństwie do Crashlytics, Sentry zapewnia szczegółowe śledzenie (breadcrumbs), monitorowanie wydajności i wsparcie dla React Native. Pozwala przeglądać stan aplikacji w momencie błędu. IT Sectr zaleca Sentry dla projektów wymagających pełnej kontroli nad obsługą błędów w rozwoju mobilnym.
Error Boundary to komponent React, który łapie błędy JavaScript w drzewie komponentów potomnych i wyświetla zastępczy interfejs użytkownika, zapobiegając całkowitemu zawieszeniu aplikacji. Error Boundary to kluczowy komponent do obsługi błędów w React Native. Używaj error boundaries dla krytycznych ekranów i nawigacji. Obsługa błędów w aplikacjach mobilnych na React Native wymaga prawidłowej konfiguracji Error Boundary na najwyższym poziomie.
Error Boundary jest tworzony przez componentDidCatch(error, errorInfo) lub static getDerivedStateFromError(error). Nie łapie błędów w kodzie asynchronicznym (setTimeout, requestAnimationFrame), renderowaniu po stronie serwera ani błędach natywnych (Native Modules). Do rejestrowania używaj SDK crash reporting wewnątrz componentDidCatch. Error Boundary to prosty, ale skuteczny program obsługi błędów dla warstwy interfejsu użytkownika.
Błąd krytyczny to nieobsłużony wyjątek, który powoduje awarię aplikacji. Błąd niekrytyczny to wyjątek, który złapałeś i obsłużyłeś, ale wskazuje na problem w kodzie. Błędy niekrytyczne są rejestrowane przez Crashlytics/Sentry i pomagają znaleźć błędy, zanim staną się krytyczne. Zarówno błędy krytyczne, jak i niekrytyczne wymagają prawidłowej obsługi błędów w rozwoju mobilnym.
Często zadawane pytania
try-catch to mechanizm językowy dla wyjątków. Result to typ opakowujący, który wymusza obsługę błędów w czasie kompilacji. W IT Sectr preferujemy Result dla logiki biznesowej i try-catch do pracy z systemami zewnętrznymi. Oba podejścia są częścią ogólnej obsługi błędów w Kotlinie.
Error Boundary to komponent React, który łapie błędy JavaScript w drzewie komponentów potomnych i wyświetla zastępczy interfejs użytkownika zamiast zawieszać całą aplikację. Nie łapie błędów w kodzie asynchronicznym ani renderowaniu po stronie serwera. Error Boundary to ważny element obsługi błędów w aplikacjach mobilnych na React Native.
Crashlytics (Firebase) to najlepszy wybór na początek: bezpłatny, prosta integracja, automatyczne grupowanie awarii. Sentry jest dla projektów wymagających szczegółowego śledzenia błędów i monitorowania wydajności. Wybór narzędzia do obsługi błędów zależy od budżetu i wymagań monitorowania.
Błąd krytyczny to awaria aplikacji (nieprzechwycony wyjątek). Błąd niekrytyczny to wyjątek, który złapałeś i obsłużyłeś, ale wskazuje na problem w kodzie. Błędy niekrytyczne są rejestrowane osobno i pomagają znaleźć błędy, zanim staną się krytyczne. Obsługa błędów w aplikacji mobilnej powinna obejmować monitorowanie obu typów.
guard let jest używany do wczesnego wyjścia z funkcji, gdy brakuje wartości — to czyni kod bardziej liniowym i czytelnym. if-let jest odpowiedni, gdy optional jest potrzebny wewnątrz bloku i nie jest wymagane wyjście z funkcji. guard let jest preferowany do walidacji parametrów wejściowych i jest częścią obsługi błędów w iOS.
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.