معالجة الأخطاء هي مهارة أساسية لمطوري تطبيقات الجوال. وفقًا لـ HackerOne (2025)، 62% من خروقات البيانات تحدث بسبب الاستثناءات غير المعالجة. المعالجة الصحيحة للأخطاء لا تمنع الأعطال فحسب، بل تحمي أيضًا بيانات المستخدم. دعنا نستعرض الأساليب لكل من iOS وAndroid وReact Native.
الخلاصة
معالجة الأخطاء في Swift تُبنى على أربع آليات رئيسية: do-catch وthrows وguard let وif-let. على عكس العديد من اللغات، Swift لا يسمح باستثناءات غير ملتقطة — كل خطأ يجب معالجته صراحة أو الإعلان عنه عبر throws. معالجة الأخطاء هي مهارة حاسمة لتطوير تطبيقات الجوال، وتؤثر بشكل مباشر على استقرار التطبيق.
do-catch هو الكتلة القياسية لاستدعاء الدوال المميزة بـ throws. داخل do، يتم استدعاء دالة باستخدام try، وإذا ألقت خطأ، ينتقل التحكم إلى catch. يمكن معالجة أنواع مختلفة من الأخطاء عبر pattern matching. إذا لم تتم معالجة الخطأ، ينتقل إلى أعلى المكدس (Error Propagation). لمعالجة فعالة للأخطاء في iOS، استخدم do-catch كآلية رئيسية.
Throw يُعلن في توقيع الدالة: func fetchData() throws -> Data. هذا يعني أن الكود المستدعي يجب أن يعالج الخطأ عبر try أو try? أو try!. try? يحول الخطأ إلى nil، try! يسبب تعطلًا عند الخطأ (استخدمه فقط إذا كنت متأكدًا من النجاح). معالجة الأخطاء عبر throw هي ممارسة إلزامية في Swift.
Guard let هو بناء للخروج المبكر من دالة إذا كانت القيمة nil. على عكس if-let، guard let يتطلب خروجًا (return أو throw أو break) في فرع else. هذا يجعل الكود أكثر تسطحًا وقابلية للقراءة — بدون كتل if المتداخلة. إذا كان optional لا يمكن أن يكون nil — استخدم force unwrap (!)، فقط عندما تكون متأكدًا تمامًا. في تطبيق الجوال، guard let يساعد في تجنب الأعطال عند معالجة القيم الاختيارية.
Optional Chaining (user?.address?.city) وnil-coalescing (??) هما سكر نحوي للعمل مع optionals دون فك التغليف. في IT Sectr، نستخدم guard let للتحقق من صحة معلمات الإدخال لواجهة API ونفرض على الفريق تجنب force unwrap دون تعليق صريح. معالج الأخطاء على كل مستوى يحمي من الأعطال غير المتوقعة.
Kotlin هو اللغة الرئيسية لتطوير Android. يرث try-catch من Java لكنه يضيف بدائل أكثر أمانًا: عامل elvis وrequire وcheck وsealed class. معالجة الأخطاء في Kotlin تُبنى على مزيج من هذه الآليات. على عكس Swift، Kotlin لا يتطلب معالجة الاستثناءات المُفحَصة (جميع الاستثناءات غير مُفحَصة). لمعالجة الأخطاء في تطبيقات الجوال على Android، استخدم sealed class كنمط رئيسي.
Try-catch في Kotlin يعمل كتعبير — يُرجع قيمة. val result = try { fetchData() } catch (e: Exception) { fallbackValue }. هذا يقلل الكود. عامل Elvis (?:) هو نظير nil-coalescing للأنواع القابلة للعدم: val name = user?.name ?: "Guest". لمعالجة الأخطاء في تطبيقات الجوال، try-catch كتعبير هو النهج الأكثر إيجازًا.
Sealed class أداة قوية لنمذجة حالات النجاح والخطأ. sealed class NetworkResult { data class Success(val data: T) : NetworkResult(); data class Error(val message: String) : NetworkResult() }. عند استخدامه في تعبير when، يتحقق المترجم من اكتمال الفروع. معالجة الأخطاء عبر sealed class تضمن عدم ترك أي حالة دون معالجة.
// Sealed class + try-catch — النمط النموذجي لـ 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}")
}
}
في المثال، sealed class NetworkResult يُنمذج حالتين: النجاح مع البيانات والخطأ مع رسالة. الدالة fetchUser تُرجع نتيجة في كل الأحوال، والكود المستدعي يعالج كلا الفرعين عبر when. هذا يزيل احتمال وجود خطأ غير مُعالج. معالجة الأخطاء عبر sealed class هي المعيار لتطوير Android في IT Sectr.
Result هو نوع مدمج في Kotlin لتمثيل نتيجة عملية قد تفشل. يُجبر على معالجة النجاح والفشل عبر fold أو getOrThrow أو map. Result مفيد في السلاسل غير المتزامنة (coroutines). معالجة الأخطاء باستخدام Result هي معيار لتطوير تطبيقات الجوال في Kotlin.
Either هو نوع وظيفي من مكتبة Arrow يسمح بإرجاع قيمة من أحد نوعين (Left — خطأ، Right — نجاح). على عكس Result، Either يمكن أن يحتوي على أي نوع خطأ معرف من قبل المستخدم. للمشاريع البسيطة، Result المدمج كافٍ؛ للمشاريع المعقدة، استخدم Either من Arrow. اختيار أداة معالجة الأخطاء يعتمد على تعقيد المشروع.
انتشار الخطأ هو آلية ينتشر فيها الخطأ لأعلى مكدس الاستدعاءات حتى تتم معالجته. في Kotlin، يحدث هذا افتراضيًا (استثناءات غير مُفحَصة). في Swift، هذا ينطبق فقط على الدوال المميزة بـ throws. مع Result وEither، الأخطاء لا تنتشر — تبقى في النوع ويجب عليك معالجتها. هذا يجعل معالجة الأخطاء في تطبيقات الجوال أكثر أمانًا.
| المعامل | iOS (Swift) | Android (Kotlin) |
|---|---|---|
| الآلية الأساسية | do-catch + throws | try-catch (expression) |
| Optional/Nullable | guard let, if-let, ?? | ?. let, elvis (?:) |
| النهج الوظيفي | Result (Swift 5+) | Result, Either (Arrow) |
| نمذجة الأخطاء | Enum: Error | Sealed class |
| الاستثناءات المُفحَصة | نعم (throws) | لا (كلها غير مُفحَصة) |
| Non-fatal | os_log, Crashlytics | Timber, Crashlytics |
الجدول يظهر الاختلافات الرئيسية. iOS يتطلب إعلانًا صريحًا للأخطاء (throws)، مما يجعل الكود أكثر أمانًا لكنه أكثر إسهابًا. Android يعتمد على انضباط المطور. في IT Sectr، نستخدم sealed class لـ Android وthrows لـ iOS — هذه هي أفضل ممارسة لكلا المنصتين لمعالجة الأخطاء في تطبيقات الجوال.
الإبلاغ عن الأعطال هو نظام لجمع وتحليل أعطال التطبيق. الإبلاغ عن الأعطال هو جزء أساسي من معالجة الأخطاء في الإنتاج. بدونه، لن تعرف بالمشاكل إلا من المستخدمين، وهذا غير مقبول للإنتاج. أداتان رئيسيتان: Firebase Crashlytics (مجاني) وSentry (مجاني للاستخدام الأساسي). لمعالجة الأخطاء في تطبيقات الجوال، قم دائمًا بتطبيق الإبلاغ عن الأعطال من الإصدار الأول.
Crashlytics هو جزء من Firebase. يجمع الأعطال تلقائيًا، ويجمعها حسب مكدس الاستدعاءات، ويظهر عدد المستخدمين المتأثرين. يدعم تسجيل الأخطاء غير المميتة عبر recordException(). التكامل: أضف SDK إلى build.gradle (Android) أو Podfile (iOS). Crashlytics هو أفضل أداة مجانية لمعالجة الأخطاء عند بدء مشروع.
Sentry هو نظام متعدد المنصات لمراقبة الأخطاء. على عكس Crashlytics، Sentry يوفر تتبعًا مفصلاً (breadcrumbs) ومراقبة الأداء ودعمًا لـ React Native. يسمح بعرض حالة التطبيق في لحظة الخطأ. IT Sectr يوصي بـ Sentry للمشاريع التي تحتاج تحكمًا كاملاً في معالجة الأخطاء في تطوير تطبيقات الجوال.
Error Boundary هو مكون React يلتقط أخطاء JavaScript في شجرة المكونات الفرعية ويعرض واجهة مستخدم احتياطية، مما يمنع انهيار التطبيق بالكامل. Error Boundary هو مكون رئيسي لمعالجة الأخطاء في React Native. استخدم error boundaries للشاشات الحرجة والتنقل. معالجة الأخطاء في تطبيقات الجوال على React Native تتطلب إعدادًا صحيحًا لـ Error Boundary في المستوى العلوي.
يتم إنشاء Error Boundary عبر componentDidCatch(error, errorInfo) أو static getDerivedStateFromError(error). لا يلتقط الأخطاء في الكود غير المتزامن (setTimeout, requestAnimationFrame) أو التصيير من جانب الخادم أو الأخطاء الأصلية (Native Modules). للتسجيل، استخدم SDK للإبلاغ عن الأعطال داخل componentDidCatch. Error Boundary هو معالج أخطاء بسيط لكنه فعال لطبقة واجهة المستخدم.
الخطأ المميت هو استثناء غير معالج يؤدي إلى تعطل التطبيق. الخطأ غير المميت هو استثناء التقطته وعالجته، لكنه يشير إلى مشكلة في الكود. الأخطاء غير المميتة تُسجل عبر Crashlytics/Sentry وتساعد في العثور على الأخطاء قبل أن تصبح مميتة. كل من الأخطاء المميتة وغير المميتة تتطلب معالجة صحيحة للأخطاء في تطوير تطبيقات الجوال.
الأسئلة الشائعة
try-catch هو آلية لغة للاستثناءات. Result هو نوع غلاف يُجبر على معالجة الخطأ في وقت الترجمة. في IT Sectr، نفضل Result لمنطق الأعمال وtry-catch للعمل مع الأنظمة الخارجية. كلا النهجين جزء من معالجة الأخطاء العامة في Kotlin.
Error Boundary هو مكون React يلتقط أخطاء JavaScript في شجرة المكونات الفرعية ويعرض واجهة مستخدم احتياطية بدلاً من انهيار التطبيق بالكامل. لا يلتقط الأخطاء في الكود غير المتزامن أو التصيير من جانب الخادم. Error Boundary عنصر مهم في معالجة الأخطاء في تطبيقات الجوال على React Native.
Crashlytics (Firebase) هو الخيار الأفضل للبدء: مجاني، تكامل بسيط، تجميع تلقائي للأعطال. Sentry للمشاريع التي تحتاج تتبعًا مفصلاً للأخطاء ومراقبة الأداء. اختيار أداة معالجة الأخطاء يعتمد على الميزانية ومتطلبات المراقبة.
الخطأ المميت هو تعطل التطبيق (استثناء غير ملتقط). الخطأ غير المميت هو استثناء التقطته وعالجته، لكنه يشير إلى مشكلة في الكود. الأخطاء غير المميتة تُسجل بشكل منفصل وتساعد في العثور على الأخطاء قبل أن تصبح مميتة. معالجة الأخطاء في تطبيق الجوال يجب أن تشمل مراقبة كلا النوعين.
guard let يُستخدم للخروج المبكر من دالة عند عدم وجود قيمة — هذا يجعل الكود أكثر خطية وقابلية للقراءة. if-let مناسب عندما يكون optional مطلوبًا داخل كتلة ولا يتطلب خروجًا من الدالة. guard let مفضل للتحقق من صحة معلمات الإدخال وهو جزء من معالجة الأخطاء في iOS.
ملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.