Gestionarea erorilor este o abilitate fundamentală pentru dezvoltatorii mobili. Potrivit HackerOne (2025), 62% din scurgerile de date au loc din cauza excepțiilor netratate. Gestionarea corectă a erorilor nu numai că previne crash-urile, dar protejează și datele utilizatorilor. Să analizăm abordările pentru iOS, Android și React Native.
Puncte cheie
Gestionarea erorilor în Swift se bazează pe patru mecanisme cheie: do-catch, throws, guard let și if-let. Spre deosebire de multe limbaje, Swift nu permite excepții neprinse — fiecare eroare trebuie tratată explicit sau declarată prin throws. Gestionarea erorilor este o abilitate critică pentru dezvoltarea mobilă, având un impact direct asupra stabilității aplicației.
do-catch este blocul standard pentru apelarea funcțiilor marcate cu throws. În interiorul do, o funcție este apelată cu try, iar dacă aruncă o eroare, controlul trece la catch. Diferite tipuri de erori pot fi tratate prin pattern matching. Dacă o eroare nu este tratată, se propagă în sus pe stivă (Error Propagation). Pentru o gestionare eficientă a erorilor în iOS, folosește do-catch ca mecanism principal.
Throw este declarat în semnătura funcției: func fetchData() throws -> Data. Aceasta înseamnă că codul apelant trebuie să trateze eroarea prin try, try? sau try!. try? convertește eroarea în nil, try! provoacă un crash la eroare (folosește doar dacă ești sigur de succes). Gestionarea erorilor prin throw este o practică obligatorie în Swift.
Guard let este o construcție pentru ieșirea timpurie dintr-o funcție dacă valoarea este nil. Spre deosebire de if-let, guard let necesită o ieșire (return, throw, break) în ramura else. Acest lucru face codul mai plat și mai lizibil — fără blocuri if imbricate. Dacă un optional nu poate fi nil — folosește force unwrap (!), doar când ești absolut sigur. Într-o aplicație mobilă, guard let ajută la evitarea crash-urilor la tratarea valorilor opționale.
Optional Chaining (user?.address?.city) și nil-coalescing (??) sunt zahăr sintactic pentru lucrul cu optionals fără despachetare. La IT Sectr, folosim guard let pentru validarea parametrilor de intrare API și impunem echipei să evite force unwrap fără un comentariu explicit. Un gestionar de erori la fiecare nivel protejează împotriva defecțiunilor neașteptate.
Kotlin este limbajul principal pentru dezvoltarea Android. Moștenește try-catch din Java, dar adaugă alternative mai sigure: operatorul elvis, require, check și sealed class. Gestionarea erorilor în Kotlin se bazează pe o combinație a acestor mecanisme. Spre deosebire de Swift, Kotlin nu necesită tratarea excepțiilor verificate (toate excepțiile sunt neverificate). Pentru gestionarea erorilor în aplicațiile mobile pe Android, folosește sealed class ca model principal.
Try-catch în Kotlin funcționează ca o expresie — returnează o valoare. val result = try { fetchData() } catch (e: Exception) { fallbackValue }. Acest lucru reduce codul. Operatorul Elvis (?:) este un analog al nil-coalescing pentru tipurile nullable: val name = user?.name ?: "Guest". Pentru gestionarea erorilor în aplicațiile mobile, try-catch ca expresie este cea mai concisă abordare.
Sealed class este un instrument puternic pentru modelarea stărilor de succes și eroare. sealed class NetworkResult { data class Success(val data: T) : NetworkResult(); data class Error(val message: String) : NetworkResult() }. Când este utilizată într-o expresie when, compilatorul verifică exhaustivitatea ramurilor. Gestionarea erorilor prin sealed class garantează că nicio stare nu rămâne netratată.
// Sealed class + try-catch — model tipic pentru Android
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}")
}
}
În exemplu, sealed class NetworkResult modelează două stări: succes cu date și eroare cu mesaj. Funcția fetchUser returnează un rezultat în orice caz, iar codul apelant tratează ambele ramuri prin when. Aceasta elimină posibilitatea unei erori netratate. Gestionarea erorilor prin sealed class este standardul pentru dezvoltarea Android la IT Sectr.
Result este un tip încorporat în Kotlin pentru a reprezenta rezultatul unei operațiuni care poate eșua. Forțează tratarea succesului și eșecului prin fold, getOrThrow sau map. Result este util în lanțuri asincrone (coroutines). Gestionarea erorilor cu Result este un standard pentru dezvoltarea mobilă în Kotlin.
Either este un tip funcțional din biblioteca Arrow care permite returnarea unei valori dintr-unul din două tipuri (Left — eroare, Right — succes). Spre deosebire de Result, Either poate conține orice tip de eroare definit de utilizator. Pentru proiecte simple, Result încorporat este suficient; pentru proiecte complexe, folosește Either din Arrow. Alegerea instrumentului de gestionare a erorilor depinde de complexitatea proiectului.
Propagarea erorilor este un mecanism prin care o eroare se propagă în sus pe stiva de apeluri până când este tratată. În Kotlin, aceasta se întâmplă implicit (excepții neverificate). În Swift, se aplică doar funcțiilor marcate cu throws. Cu Result și Either, erorile nu se propagă — rămân în tip și trebuie să le tratezi. Acest lucru face gestionarea erorilor în aplicațiile mobile mai sigură.
| Parametru | iOS (Swift) | Android (Kotlin) |
|---|---|---|
| Mecanism de bază | do-catch + throws | try-catch (expression) |
| Optional/Nullable | guard let, if-let, ?? | ?. let, elvis (?:) |
| Abordare funcțională | Result (Swift 5+) | Result, Either (Arrow) |
| Modelarea erorilor | Enum: Error | Sealed class |
| Excepții verificate | Da (throws) | Nu (toate neverificate) |
| Non-fatal | os_log, Crashlytics | Timber, Crashlytics |
Tabelul arată diferențele cheie. iOS necesită declararea explicită a erorilor (throws), făcând codul mai sigur, dar mai verbose. Android se bazează pe disciplina dezvoltatorului. La IT Sectr, folosim sealed class pentru Android și throws pentru iOS — aceasta este cea mai bună practică a ambelor platforme pentru gestionarea erorilor în aplicațiile mobile.
Raportarea crash-urilor este un sistem de colectare și analiză a crash-urilor aplicației. Raportarea crash-urilor este o parte esențială a gestionării erorilor în producție. Fără ea, afli despre probleme de la utilizatori, ceea ce este inacceptabil pentru producție. Două instrumente principale: Firebase Crashlytics (gratuit) și Sentry (gratuit pentru utilizare de bază). Pentru gestionarea erorilor în aplicațiile mobile, implementează întotdeauna raportarea crash-urilor de la prima lansare.
Crashlytics face parte din Firebase. Colectează automat crash-urile, le grupează după stiva de apeluri și arată numărul de utilizatori afectați. Suportă înregistrarea erorilor non-fatale prin recordException(). Integrare: adaugă SDK-ul în build.gradle (Android) sau Podfile (iOS). Crashlytics este cel mai bun instrument gratuit pentru gestionarea erorilor la începutul unui proiect.
Sentry este un sistem de monitorizare a erorilor cross-platform. Spre deosebire de Crashlytics, Sentry oferă urmărire detaliată (breadcrumbs), monitorizare a performanței și suport pentru React Native. Permite vizualizarea stării aplicației în momentul erorii. IT Sectr recomandă Sentry pentru proiectele care au nevoie de control complet asupra gestionării erorilor în dezvoltarea mobilă.
Error Boundary este o componentă React care prinde erori JavaScript în arborele componentelor copil și afișează o interfață de rezervă, prevenind un crash complet al aplicației. Error Boundary este o componentă cheie pentru gestionarea erorilor în React Native. Folosește error boundaries pentru ecrane critice și navigare. Gestionarea erorilor în aplicațiile mobile pe React Native necesită o configurare adecvată a Error Boundary la nivelul superior.
Error Boundary este creat prin componentDidCatch(error, errorInfo) sau static getDerivedStateFromError(error). Nu prinde erori în cod asincron (setTimeout, requestAnimationFrame), randare pe server sau erori native (Native Modules). Pentru înregistrare, folosește SDK-ul de raportare a crash-urilor în interiorul componentDidCatch. Error Boundary este un gestionar de erori simplu, dar eficient pentru stratul de interfață.
Eroare fatală este o excepție netratată care provoacă un crash al aplicației. Eroare non-fatală este o excepție pe care ai prins-o și ai tratat-o, dar indică o problemă în cod. Erorile non-fatale sunt înregistrate prin Crashlytics/Sentry și ajută la găsirea bug-urilor înainte ca acestea să devină fatale. Atât erorile fatale, cât și cele non-fatale necesită o gestionare adecvată a erorilor în dezvoltarea mobilă.
Întrebări frecvente
try-catch este un mecanism de limbaj pentru excepții. Result este un tip wrapper care forțează gestionarea erorilor la compilare. La IT Sectr, preferăm Result pentru logica de afaceri și try-catch pentru lucrul cu sisteme externe. Ambele abordări fac parte din gestionarea generală a erorilor în Kotlin.
Error Boundary este o componentă React care prinde erori JavaScript în arborele componentelor copil și afișează o interfață de rezervă în loc să facă crash întreaga aplicație. Nu prinde erori în cod asincron sau randare pe server. Error Boundary este un element important al gestionării erorilor în aplicațiile mobile pe React Native.
Crashlytics (Firebase) este cea mai bună alegere pentru început: gratuit, integrare simplă, grupare automată a crash-urilor. Sentry este pentru proiecte care au nevoie de urmărire detaliată a erorilor și monitorizare a performanței. Alegerea instrumentului de gestionare a erorilor depinde de buget și de cerințele de monitorizare.
Eroare fatală este un crash al aplicației (excepție neprinsă). Eroare non-fatală este o excepție pe care ai prins-o și ai tratat-o, dar indică o problemă în cod. Erorile non-fatale sunt înregistrate separat și ajută la găsirea bug-urilor înainte ca acestea să devină fatale. Gestionarea erorilor într-o aplicație mobilă ar trebui să includă monitorizarea ambelor tipuri.
guard let este folosit pentru ieșirea timpurie dintr-o funcție când o valoare lipsește — acest lucru face codul mai liniar și mai lizibil. if-let este potrivit când un optional este necesar în interiorul unui bloc și nu este necesară ieșirea din funcție. guard let este preferat pentru validarea parametrilor de intrare și face parte din gestionarea erorilor în iOS.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.