تخطَّ إلى المحتوى

٢١ يوليو ٢٠٢٦

حل خطأ Unexpectedly found nil while unwrapping an Optional value في Swift

شارك المقال:

من أكثر تعطّلات (crashes) تطبيقات Swift و iOS شهرة، وأكثرها إرباكًا للمبتدئين لأنها تظهر فجأة دون أي خطأ ترجمة سابق:

Fatal error: Unexpectedly found nil while unwrapping an Optional value

الرسالة واضحة لو فهمت مفهوم الاختيارية (Optional) في Swift: حاولت الوصول لقيمة افترضت أنها موجودة قطعًا، لكنها كانت nil فعليًا عند التشغيل — وSwift اختار التعطّل الفوري بدل الاستمرار بحالة غير آمنة.

السبب الجذري: الفكّ الإجباري !

أي متغيّر اختياري (Type?) قد يحمل قيمة أو nil. عامل الفكّ الإجباري ! يخبر المترجم "أنا متأكد أن هذه القيمة موجودة، أعطني إياها مباشرة دون فحص". لو كان مخطئًا، يتعطّل البرنامج بهذه الرسالة تحديدًا:

var username: String? = nil
print(username!)   // 💥 Fatal error: Unexpectedly found nil...

المشكلة نادرًا ما تكون بهذا الوضوح في الكود الحقيقي — غالبًا الفكّ الإجباري مختبئ داخل دالة أو مكتبة أو حتى Storyboard.

أشهر أماكن حدوثه في تطبيقات iOS

المكانالسبب النموذجي
@IBOutletالخاصية مُعرَّفة Type! لكن الوصلة بالـ Storyboard انقطعت أو حُذف العنصر
dictionary["key"]!المفتاح غير موجود فعليًا بالقاموس عند هذا الاستدعاء
URL(string: someText)!النص لا يمثّل رابطًا صالحًا (مسافة، رمز غير مسموح...)
array.first! أو array.last!المصفوفة فارغة في تلك اللحظة
خاصية Type! بصنفاستُخدمت قبل أن يهيّئها كود آخر (مثل viewDidLoad لم يُنفَّذ بعد)

الحل: استبدل ! بفكّ آمن

1) if let أو guard let

الخيار الأول دائمًا. راجع درس الاختيارية في مسار Swift:

guard let url = URL(string: someText) else {
    print("رابط غير صالح: \(someText)")
    return
}
// استخدم url بأمان من هنا

2) عامل الدمج ??

مناسب عند وجود قيمة بديلة منطقية بدل التوقّف:

let name = dictionary["username"] ?? "زائر"

3) IBOutlet: تحقّق من الوصلة نفسها

لو الخطأ يحدث فور فتح شاشة معينة، افتح الـ Storyboard وتأكّد أن كل @IBOutlet ما زال موصولًا فعليًا بعنصره — حذف أو إعادة تسمية عنصر بالواجهة يفصل الوصلة القديمة صامتًا دون تحذير وقت الترجمة.

4) رسالة تشخيص أوضح بدل الرسالة العامة

إذا كانت القيمة يجب أن تكون موجودة فعلًا (خطأ برمجي لا يجب السماح باستمراره)، استخدم guard مع رسالة توضّح المكان بدل ! الصامت:

guard let user = currentUser else {
    fatalError("currentUser لازم يكون معيّن قبل استدعاء هذه الدالة")
}

النتيجة تعطّل مماثل عند الحاجة الفعلية، لكن برسالة تقودك للسطر الصحيح فورًا بدل البحث في كل الكود عن !.

قائمة تحقّق سريعة

  • ابحث بالكود عن كل ! بعد اسم متغيّر أو دالة ترجع Optional — هل أنت متأكد 100% من كل واحدة؟
  • إن كان التعطّل بشاشة SwiftUI/UIKit معيّنة → افحص وصلات @IBOutlet بالـ Storyboard أولًا.
  • إن كان بقراءة قاموس أو مصفوفة → استخدم dictionary["key"] (بدون !) أو array.first واتعامل معها كـ Optional.
  • إن كان بتحويل نص لرابط أو رقم → URL(string:) و Int(text) كلاهما يرجعان Optional دائمًا لأن التحويل قد يفشل.

الخلاصة

هذا الخطأ ليس عيبًا بلغة Swift، بل هو أمان مقصود: اللغة تجبرك على التعامل مع غياب القيمة صراحةً بدل تجاهله كما تفعل لغات أخرى. كل ما عليك فعله هو استبدال ! بفكّ آمن (if let / guard let / ??) في أي موضع لا تملك فيه ضمانًا مطلقًا — وستختفي هذه الرسالة نهائيًا من تطبيقك.

أكمل تعمّقك بمفهوم الاختيارية كاملًا في مسار Swift، وإذا كنت تقارن بين تطوير iOS وأندرويد راجع الفرق بين Swift و Kotlin.

📚 مصادر رسمية للتعمّق: كتاب Swift الرسمي

الأسئلة الشائعة

ما الفرق بين هذا الخطأ وخطأ Thread 1: signal SIGABRT؟

SIGABRT اسم الإشارة العامة التي يرسلها النظام عند تعطّل التطبيق بأي سبب. Unexpectedly found nil while unwrapping an Optional value هو السبب المحدّد المكتوب أسفل تلك الإشارة في نافذة الأخطاء — دائمًا ابحث عن سطر Fatal error أسفل SIGABRT لتعرف السبب الحقيقي.

هل استخدام ! ممنوع نهائيًا في Swift؟

لا. ! مفيد ومقصود لما تملك يقينًا مطلقًا ومضمونًا برمجيًا بوجود القيمة (مثل خاصية IBOutlet موصولة فعليًا ودائمًا بالـ Storyboard). المشكلة ليست باستخدامه، بل باستخدامه لقيمة قد تكون nil فعليًا في بعض المسارات — عندها if let أو guard let أضمن.

كيف أوقف التطبيق عن التعطّل الفوري وأرى رسالة أوضح بدل الرسالة العامة؟

استبدل الفكّ الإجباري بـ guard let مع رسالة مخصّصة، أو استخدم precondition(value != nil, "رسالة توضّح أين ولماذا") — التطبيق سيتعطّل أيضًا إن كانت القيمة حقًا مطلوبة، لكن برسالة تشرح السبب فورًا بدل رسالة Swift العامة.

اقرأ أيضًا

تصفّح كل المقالات في المدوّنة، أو ابدأ التعلّم من المسارات و خرائط الطريق.