Non-Fatal Error — uygulamayı sonlandırmayan ve programın yürütülmesine devam edilmesini sağlayan bir hatadır. Fatal error'un aksine, ölümcül olmayan hatalar kullanıcı oturumunu kaybetmeden yakalanabilir, işlenebilir ve günlüğe kaydedilebilir. Firebase Crashlytics Belgeleri, 2024'e göre, üretim uygulamalarında kaydedilen tüm hataların yaklaşık %70'i ölümcül değildir, ancak bunları görmezden gelmek teknik borç birikimine ve kullanıcı deneyiminin kademeli olarak bozulmasına yol açar. Ölümcül olmayan hataların doğru şekilde ele alınması, mobil geliştiricinin temel becerilerinden biridir.
Önemli Noktalar
Non-Fatal Error — sürecin sonlandırılmasına neden olmayan bir istisna veya hata durumudur. Uygulama çalışmaya devam eder, ancak hatalı bir durumda olabilir: veriler yüklenmedi, istek gönderilmedi, arayüz öğesi görüntülenmedi. Kullanıcı ya hatayı fark etmez ya da bir mesaj görür ve uygulamayı kullanmaya devam eder.
Ölümcül olmayan bir hata her zaman programa bir kurtarma yolu bırakır. Hata işleyici alternatif veriler sağlayabilir, işlemi yeniden deneyebilir veya bir arayüz yer tutucusu gösterebilir. Temel amaç çökmeyi önlemek ve kabul edilebilir bir kullanıcı deneyimi sürdürmektir. Geliştirici her catch bloğunda açıkça bir kurtarma senaryosu planlamalıdır.
Instabug 2024'e göre, kullanıcıların %65'i iki başarısız etkileşimden sonra bir uygulamayı kaldırır. Dikkate alınmayan ölümcül olmayan hatalar birikir ve genel kaliteyi düşürür. Ölümcül olmayan hataların sistematik olarak günlüğe kaydedilmesi ve düzeltilmesi, kullanıcı tutulumunu iyileştirmenin ve uygulama mağazası puanlarını artırmanın doğrudan bir yoludur.
Ağ hataları mobil uygulamalarda en yaygın ölümcül olmayan hata türüdür. Bağlantı zaman aşımı, ağ kaybı, yanlış sunucu durum kodu — tüm bu durumlar çökme olmadan yakalanır ve işlenir. Kullanıcıya yeniden deneme seçeneğiyle birlikte hizmet kullanılamazlık mesajı gösterilir. Üstel geri bildirimli yeniden deneme deseni ağ hataları için tipiktir.
Yanlış sunucu yanıt biçimi, zorunlu alan eksikliği, geçersiz veri türü — ayrıştırma hataları, uygulama hatalı verileri doğru şekilde işlerse ölümcül değildir. Tipik yaklaşım, varsayılan yedek değerler kullanmak ve daha sonra sunucu tarafında analiz için istek bağlamıyla birlikte ayrıştırma hatasını günlüğe kaydetmektir.
Görüntü yükleme sorunları, yanlış yazı tipleri, düzen hataları — bunların tümü ölümcül değildir ancak kullanıcı deneyimini bozar. Yer tutucu görüntüler ve yedek değerler boş ekranlardan kaçınmaya ve hataları daha az fark edilir kılmaya yardımcı olur. React Native'de, yedek bileşen görüntüleyen Error Boundary UI hataları için kullanılır.
Hesaplama hataları, durum uyuşmazlıkları, yanlış ekran geçişleri — mantık hataları genellikle çökmeye neden olmaz ancak uygulamanın yanlış davranışına yol açar. Sistematik günlüğe kaydetme ve izleme olmadan bunları tespit etmek daha zordur çünkü çökme raporu oluşturmazlar ve kullanıcı şikayetine kadar fark edilmezler.
Non-Fatal Error, programa çalışmaya devam etme şansı bırakmasıyla fatal error'dan ayrılır. Fatal error, uygulamanın kurtulamadığı bir durumdur: boş işaretçi başvurusu, yığın taşması, bellek yetersizliği. Ölümcül olmayan bir hata yakalanabilir, işlenebilir ve yürütme devam edebilirken, fatal error uygulamanın yeniden başlatılmasını gerektirir.
| Özellik | Non-Fatal Error | Fatal Error |
|---|---|---|
| Uygulama sonlandırma | Hayır | Evet |
| Kurtarma mümkün | Evet, catch bloğu ile | Hayır |
| Günlüğe kaydetme | Koddan recordException ile | Sadece çökme raporlayıcısı ile |
| UX etkisi | Geçici rahatsızlık | Tam oturum başarısızlığı |
| Örnek | Ağ zaman aşımı, ayrıştırma hatası | NullPointerException, OOM |
Ölümcül olmayan ile ölümcül arasındaki sınır uygulamaya bağlı olabilir. Bir uygulamada ağ zaman aşımı ölümcül olmayan olarak işlenirken (1–2 saniye sonra yeniden dene), başka bir uygulamada ölümcül olabilir (işleyici yoksa çökme). Kaliteli hata işleme, potansiyel olarak ölümcül durumları ölümcül olmayana dönüştürerek uygulama kararlılığını artırır. Yüksek güvenilirlik gereksinimleri olan bir mobil uygulama geliştirirken hata işleme sistemi tasarlamak temel mimari görevlerden biridir. Yerleşik bir izleme sistemi, ekibin ölümcül olmayan hataları çok sayıda kullanıcıyı etkilemeden önce hızlıca tespit etmesini ve düzeltmesini sağlar.
Firebase Crashlytics, mobil uygulamalarda ölümcül olmayan hataları günlüğe kaydetmek için birincil araçtır. recordException yöntemi, uygulamayı kesintiye uğratmadan tam yığın izi ve yürütme bağlamıyla ölümcül olmayan bir istisnayı yakalamayı sağlar. Çökme raporlarının aksine, yakalanan istisnaları günlüğe kaydetmek için kodun herhangi bir yerinde recordException çağrılabilir.
fun fetchUserData(userId: String) {
try {
val response = apiService.getUser(userId)
updateUI(response)
} catch (e: IOException) {
Crashlytics.log("Network error for user $userId")
Crashlytics.recordException(e)
showRetryDialog()
} catch (e: JsonParseException) {
// Non-fatal: yedek veri kullan
Crashlytics.recordException(e)
showFallbackContent()
}
}
// Özel anahtarlarla günlüğe kaydetme
Crashlytics.setCustomKey("screen", "Profile")
Crashlytics.setCustomKey("api_version", "v3")
Sentry, ölümcül olmayan hatalar için daha ayrıntılı tanılama sağlayan Crashlytics'e bir alternatiftir. Sentry SDK, istisna ayrıntılarını sunucuya gönderen captureException yöntemini sağlar. Sentry'nin temel avantajı, benzer ölümcül olmayan hataları tek bir sorunda gruplamak, yinelenme sıklığını analiz etmek ve breadcrumbs — hata öncesi kullanıcı eylemlerinin sırası — olarak yürütme bağlamı sağlamaktır.
Tüm ölümcül olmayan hataların günlüğe kaydedilmesi gerekmez. Beklenen durumlar — bağlantı olmadığında ağ hatası — seçici olarak günlüğe kaydedilebilir. Beklenmeyen hatalar — işlenmiş kodda NullPointerException, geçersiz veri biçimi, mantık hataları — her zaman günlüğe kaydedilmelidir. Her ekip kendi önem eşiğini belirler: ortalama olarak, günde 1000 kullanıcı başına 10 ila 20 benzersiz ölümcül olmayan hata normal kabul edilir. Ölümcül olmayan hatalardaki keskin artış için uyarılar ayarlamak önemlidir — bu, yeni bir API sürümüyle ilgili sorunları veya bir sürümden sonra gerilemeyi gösterebilir.
Temel işleme mekanizması, istisnayı yakalayan ve kurtarma kodunu yürüten try-catch'tir. Ağ işlemleri için tipik desen, üstel geri bildirimli yeniden denemedir. Ayrıştırma hataları için yaklaşım, varsayılan yedek değerler kullanmak ve daha sonra sunucu tarafında analiz için bağlamı günlüğe kaydetmektir.
func loadImage(from url: URL) -> UIImage? {
do {
let data = try Data(contentsOf: url)
return UIImage(data: data)
} catch {
Logger.shared.logError(error: "Image load failed: \(url)")
return UIImage(named: "placeholder")
}
}
func performRequest() async throws -> Data {
var lastError: Error? = nil
for attempt in 0..<3 {
do {
return try await URLSession.shared.data(from: url)
} catch {
lastError = error
try await Task.sleep(UInt64(pow(2, attempt)) * 1_000_000_000)
}
}
throw lastError ?? URLError(.unknown)
}
Sonuç türleri — istisnasız alternatif bir yaklaşım. Bir işlev, Success ve Failure varyantlarına sahip sealed bir Result sınıfı döndürür. Çağıran kod, her iki varyantı da açıkça işleyerek işlenmemiş hataları ortadan kaldırır. Sonuç türleri, tür düzeyinde ölümcül olmayan durumların açıkça işlenmesi için Kotlin'de (standart kütüphanede Result
Her ölümcül olmayan hata türü için bir kurtarma stratejisi planlanmalıdır: ağ hatasında önbelleğe alınmış verileri yükleme, ayrıştırma hatasında varsayılan değerleri kullanma, UI hatasında bir bileşeni yeniden başlatma. İyi bir uygulama, uygulamayla etkileşimi tamamen engellemeden kullanıcıya bir hata mesajı içeren toast veya snackbar göstermektir. Kurtarılabilir ve kurtarılamaz hatalar arasında ayrım yapmak önemlidir — ikincisi için kurtarma stratejisi farklı olacaktır, örneğin ekranı yeniden başlatmayı veya verileri temizlemeyi önermek. Önceki başarılı durumu önbelleğe almak, mobil platformlarda ölümcül olmayan hataları işlemenin genellikle en basit ve en etkili yoludur.
Sıkça Sorulan Sorular
Uyarı, derleyiciden veya statik analizörden kodda potansiyel bir sorun hakkında bir uyarıdır. Ölümcül olmayan hata, zaten meydana gelmiş ancak çökmeye neden olmamış bir çalışma zamanı istisnasıdır. Bir uyarı derlemeden önce düzeltilebilir; ölümcül olmayan hata, çalıştırma sırasında bir catch bloğu aracılığıyla işlenmelidir.
Hayır, aşırı günlüğe kaydetme izlemeyi karmaşıklaştırır. Üretimde beklenmeyen hatalar günlüğe kaydedilmeli, beklenen durumlar ise göz ardı edilmelidir: çevrimdışıyken ağ hatası seçici olarak günlüğe kaydedilebilir, ancak işlenmiş kodda NullPointerException her zaman günlüğe kaydedilmelidir. Her ekip, uygulama bağlamına göre kendi önem eşiğini belirler.
SwiftUI'de, hata durumunu izlemek için @Published errorState alanına sahip ObservableObject kullanılır. View, değişikliklere abone olur ve alternatif içerik görüntüler. iOS 17'den önce, işleyicilerle Combine kullanılıyordu; iOS 17'den itibaren, reaktif UI güncellemeleri için SwiftData ve @Observable makroları kullanılmaktadır.
Evet, hata bir zincirleme reaksiyonu tetiklerse. Örnek: ölümcül olmayan bir görüntü yükleme hatası, hatalı bir UI durumuna yol açabilir ve bu da görüntülemeye çalışıldığında çökmeye neden olabilir. Her seviyede ölümcül olmayan hataların kaliteli bir şekilde işlenmesi, bunların ölümcül seviyeye yükselmesini önler.
iOS'te ölümcül olmayan hatalar throw ile do-catch aracılığıyla işlenir; Android'de istisnalarla try-catch aracılığıyla. iOS, alanlar ve hata kodlarıyla NSError kullanır; Android, Java/Kotlin istisnalarını kullanır. Crashlytics, recordException aracılığıyla her iki platformda da aynı şekilde çalışarak birleşik bir izleme arayüzü sağlar.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun