Obsługa błędów w rozwoju mobilnym: czym jest, jakie techniki i jak ją zorganizować

Autor: IT Sectr Opublikowano: 2026-05-23 Czas czytania: 11 min

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

  • iOS używa do-catch, throw, guard let i if-let do obsługi błędów. Swift nie dopuszcza nieobsłużonych wyjątków na poziomie języka.
  • Android/Kotlin oferuje try-catch, operator elvis, sealed class i typ Result. Sealed class to potężne narzędzie do modelowania stanów błędów.
  • Kotlin Result i Either z bibliotek funkcyjnych wymuszają obsługę błędów w czasie kompilacji, czyniąc kod bardziej niezawodnym.
  • Crash Reporting (Crashlytics, Sentry) to obowiązkowe narzędzie dla produkcji. Bez niego dowiadujesz się o błędach tylko od użytkowników.
  • Error Boundary w React Native zapobiega całkowitemu zawieszeniu aplikacji z powodu błędów JavaScript. Użyj go dla komponentów głównych.

Obsługa błędów w iOS: Do-Catch, Throw, Guard Let

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 i Throw

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.

Optional/Nullable i Guard Let

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.

Obsługa błędów w Android: Try-Catch, Elvis, Sealed Class

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 i operator Elvis

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.

kotlin
// 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.

Obsługa błędów w Kotlin: Result i Either

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.

Result vs Either

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

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 mechanizmdo-catch + throwstry-catch (expression)
Optional/Nullableguard let, if-let, ???. let, elvis (?:)
Podejście funkcyjneResult (Swift 5+)Result, Either (Arrow)
Modelowanie błędówEnum: ErrorSealed class
Kontrolowane wyjątkiTak (throws)Nie (wszystkie unchecked)
Non-fatalos_log, CrashlyticsTimber, 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: Crashlytics i Sentry

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.

Firebase Crashlytics

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

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 w React Native

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.

Implementacja Error Boundary

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łędy krytyczne i niekrytyczne

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

Czym różni się try-catch od Result w Kotlinie?

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.

Czym jest Error Boundary w React Native?

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.

Czy powinienem używać Crashlytics czy Sentry dla nowego projektu?

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.

Czym jest błąd niekrytyczny i czym różni się od krytycznego?

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.

Kiedy używać guard let zamiast if-let w Swifcie?

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

  • iOS używa do-catch, throws i guard let — każdy błąd musi być zadeklarowany w sygnaturze funkcji. Obsługa błędów w iOS wymaga jawnych deklaracji.
  • Android/Kotlin oferuje try-catch jako wyrażenie, operator elvis i sealed class do modelowania błędów. Obsługa błędów w Android jest bardziej elastyczna, ale wymaga dyscypliny.
  • Sealed class i Result to najlepsze praktyki funkcyjnej obsługi błędów w Kotlinie. Eliminują nieobsłużone stany.
  • Crash Reporting (Crashlytics, Sentry) jest obowiązkowy dla produkcji. Zacznij od Crashlytics, przejdź na Sentry wraz ze wzrostem projektu. Obsługa błędów w aplikacjach mobilnych jest niemożliwa bez monitorowania.
  • Error Boundary w React Native zapobiega całkowitym awariom interfejsu użytkownika. Używaj na najwyższym poziomie nawigacji.
  • Błędy niekrytyczne są tak samo ważne jak krytyczne — wskazują problemy przed awarią aplikacji. Program obsługi błędów powinien rejestrować oba typy.
  • Global Exception Handler to ostatnia linia obrony. Zaimplementuj Thread.setDefaultUncaughtExceptionHandler (Android) lub NSSetUncaughtExceptionHandler (iOS), aby rejestrować wszystkie nieprzechwycone błędy.

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.

Omów projekt