viewWillDisappear هي طريقة UIViewController يستدعيها UIKit قبل أن تبدأ الشاشة في الاختفاء من شاشة المستخدم. وفقًا لـ Apple Developer Documentation، تستلم هذه الطريقة معلمة animated وتنطلق عند push، pop، present، dismiss وتبديل العلامات التبويبية. viewWillDisappear هو المكان الرئيسي لحفظ الحالة وتنظيف الموارد بشكل صحيح.
النقاط الرئيسية
viewWillDisappear هي طريقة UIViewController يستدعيها UIKit قبل أن تبدأ عرض الواجهة للمتحكم في الاختفاء من الشاشة. في هذه اللحظة تظل الشاشة مرئية للمستخدم، ولكن الانتقال قد بدأ بالفعل: NavigationController بدأ حركة push/pop، بدأت النافذة المنثلة في الإغلاق، أو بدأ TabBar في التبديل إلى علامة تبويب أخرى. يقوم المطور بتجاوز هذه الطريقة لتنفيذ عمليات تتطلب أن تكون الشاشة ما زالت قابلة للوصول ولكنها تستعد للإخفاء.
على عكس viewDidDisappear، التي تنطلق بعد إخفاء الشاشة، توفر viewWillDisappear آخر فرصة لحفظ البيانات وتحرير الموارد بينما لا يزال المستخدم يرى الواجهة. هذا مهم بشكل حاسم لتجربة المستخدم — يجب أن يحدث حفظ مسودة أو إيقاف مؤقت قبل أن يتحول المستخدم إلى شاشة أخرى.
تستقبل الطريقة معلمة animated، التي تشير إلى ما إذا كان الاختفاء متحركًا. القيمة true تعني أن UIKit ينفذ انتقالًا متحركًا، false تعني أن الشاشة تختفي فورًا، على سبيل المثال خلال dismiss بدون حركة أو إزالة برمجية من التسلسل الهرمي.
viewWillDisappear تتم استدعاؤها في جميع السيناريوهات حيث تتوقف الشاشة الحالية عن النشاط. دعنا نستعرض الحالات الرئيسية المحددة لتطوير iOS.
عندما يقوم UINavigationController بتنفيذ push لمتحكم جديد، يتم استدعاء viewWillDisappear على المتحكم الحالي في بداية حركة الانتقال. في هذه اللحظة تكون الشاشة الحالية ما زالت مرئية تحت المتحكم الجديد المنزلق فوقها. هذا هو السيناريو القياسي حيث ينطلق viewWillDisappear مع animated = true.
عندما يضغط المستخدم على زر الرجوع أو ينفذ تمريرة تفاعلية للرجوع إلى الخلف، يتم استدعاء viewWillDisappear على المتحكم الحالي. مع الإيماء التفاعلي يمكن أن يتم إلغاء هذا الاستدعاء إذا غير المستخدم رأيه وأعاد الشاشة إلى مكانها. هذه سمة مهمة يجب مراعاتها عند تصميم حفظ الحالة.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
saveDraftData()
NotificationCenter.default.removeObserver(self)
}
عند إغلاق نافذة منثلة، يتم استدعاء viewWillDisappear على المتحكم المغلق في بداية حركة dismiss. في هذه النقطة يمكنك إرجاع النتائج من خلال المفوض أو الإغلاق، نظرًا لأن المتحكم الذي قدم النافذة المنثلة لم يستعد السيطرة بعد.
UITabBarController يستدعي viewWillDisappear على متحكم العلامة التبويبية المغادرة فور بعد لمس المستخدم لعلامة تبويب أخرى. إذا كانت العلامة التبويبية الحالية تحتوي على عمليات نشطة — تشغيل وسائط، تنزيل ملف، مؤقت — فيجب إيقافها أو إيقافها مؤقتًا هنا.
viewWillDisappear تحل مهامًا محددة لإدارة الموارد والحالة. دعنا نستعرض السيناريوهات الرئيسية مع أمثلة الكود.
أهم مهمة لـ viewWillDisappear هي حفظ البيانات التي أدخلها المستخدم أو عدلها على الشاشة الحالية. مسودات الرسائل، حقول النموذج المحررة، الإعدادات المختارة — يجب حفظ كل هذا قبل أن تختفي الشاشة. استخدم Core Data، UserDefaults أو تخزين الملفات للاستدامة.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
guard hasUnsavedChanges else { return }
draftStorage.save(currentDraft)
}
NotificationCenter، KVO وناشري Combine الذين اشتركت فيهم في viewWillAppear أو viewDidLoad يجب إلغاؤهم في viewWillDisappear. إذا لم تفعل ذلك، ستصل الإشعارات إلى الشاشة المخفية، مما يتسبب في تحديثات واجهة المستخدم التي لا يراها المستخدم، أو — أسوأ — أعطال نتيجة الوصول إلى كائنات تم إلغاء تخصيصها.
حركات UIView التي بدأت في viewDidAppear والمؤقتات التي تعمل من خلال Timer أو DispatchSource يجب إيقافها في viewWillDisappear. الحركات المستمرة على شاشة مخفية تهدر وحدة معالجة الرسوم والبطارية بدون أي فائدة للمستخدم. أيقفها بشكل صريح باستدعاء invalidate على المؤقتات و removeAllAnimations على الطبقات.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
countdownTimer?.invalidate()
countdownTimer = nil
loadingIndicator.layer.removeAllAnimations()
}
إذا تم فتح متحكم للحصول على نتيجة — تحديد عنصر، إدخال نص، تأكيد إجراء — فإن viewWillDisappear هي آخر لحظة يوجد فيها المتحكم الأصلي في الكومة ويمكنه استقبال البيانات. استدع المفوض أو الإغلاق قبل استدعاء deinit.
الحفظ الموثوق لحالة الشاشة هي واحدة من أصعب المهام في تطوير iOS. viewWillDisappear هي عنصر مهم ولكنه ليس الوحيد في الاستراتيجية. دعنا ننظر إلى نهج شامل.
المستوى 1 — الحفظ في viewWillDisappear. حفظ سريع للبيانات الخفيفة التي يجب أن تكون متاحة فورًا عند العودة. مناسب لحالة واجهة المستخدم: موقع التمرير، القطاع المحدد، النص في حقول الإدخال. المشكلة: عند إيماء pop تفاعلي ملغى، يحدث الحفظ على الرغم من أن المستخدم بقي على الشاشة — تتم الكتابة فوق البيانات دون داعي.
المستوى 2 — الحفظ في viewDidDisappear. يقوم بدوبلة الحفظ من المستوى الأول ولكنه ينطلق فقط بعد أن يتم إخفاء الشاشة بشكل مضمون. هذا هو حافز أمان ضد الإيماءات الملغاة. ولكن إذا قمت بإلغاء الاشتراك من الإشعارات في viewWillDisappear، فقد لا يكون لدى viewDidDisappear إمكانية الوصول إلى بعض البيانات.
المستوى 3 — الحفظ من خلال إشعارات التطبيق. UIApplication.willResignActiveNotification و UIApplication.didEnterBackgroundNotification يلتقطان تصغير التطبيق. إذا صغر المستخدم التطبيق، فقد لا يكون قد تم استدعاء viewWillDisappear — ولكن الحفظ من خلال هذه الإشعارات يضمن سلامة البيانات عند انتهاء الجلسة.
| المستوى | الطريقة/الإشعار | الموثوقية | الاستخدام |
|---|---|---|---|
| 1 | viewWillDisappear | عالية | حالة واجهة المستخدم، مسودات |
| 2 | viewDidDisappear | عالية جدًا | بيانات حرجة |
| 3 | willResignActive | قصوى | عند تصغير التطبيق |
توصية: استخدم مزيجًا من المستويات الثلاثة للبيانات الحرجة للمستخدم. وللحالة غير الحرجة، يكفي المستوى الأول. من المهم عدم إعادة حفظ نفس البيانات مرارًا متعددة — استخدم علامة dirty تشير إلى أن البيانات قد تغيرت منذ آخر حفظ.
يجب إولاء اهتمام خاص للاستراتيجية لشاشات CRUD حيث يدخل المستخدم البيانات. في مثل هذه الشاشات، لا يوصى بحفظ كل ضغطة مفتاح في viewWillDisappear — هذا مفرط. استخدم الحفظ التلقائي مع تأخير (debounce) عن طريق Timer، واستخدم viewWillDisappear فقط للحفظ النهائي المجبر إذا وجدت تغييرات غير محفوظة. يوازن هذا النهج بين الأداء وسلامة البيانات.
للتطبيقات التي تستخدم Core Data، الإجراء الإضافي هو استدعاء saveContext في viewWillDisappear فقط عندما تكون هناك تغييرات فعلية في سياق الكائنات المدارة. يمنع التحقق من context.hasChanges قبل الحفظ الكتابات غير الضرورية إلى مخزن البيانات المستديم ويطيل عمر بطارية الجهاز. قم بالجمع بين هذا التحقق والحفظ العالمي في applicationDidEnterBackground.
الاستخدام غير الصحيح لـ viewWillDisappear يمكن أن يؤدي إلى فقدان البيانات، تسرب الذاكرة وسلوك تطبيق غير مستقر. دعنا نستعرض أخطاء مطوري iOS الشائعة.
الخطأ الأول — حفظ البيانات فقط في viewWillDisappear. كما نوقشنا سابقًا، مع إيماء pop تفاعلي تتم استدعاء الطريقة حتى لو لم تختف الشاشة. إذا كان للحفظ آثار جانبية — إرسال البيانات إلى الخادم، تغيير الحالة — فقد يؤدي ذلك إلى تنشيطات خاطئة. أضف تحققًا من isBeingDismissed أو isMovingFromParent.
الخطأ الثاني — عدم إلغاء الاشتراك من NotificationCenter. هذا هو واحد من أكثر تسربات الذاكرة شيوعًا في iOS. إذا اشتركت في viewWillAppear إلى UIResponder.keyboardWillShowNotification ولكن لم تلغ الاشتراك في viewWillDisappear، فسيستمر الإغلاق في العمل. عند deinit للمتحكم، سيشير الإغلاق إلى كائن تم إلغاء تخصيصه — تعطل التطبيق مضمون.
الخطأ الثالث — تنفيذ عمليات متزامنة ثقيلة. حفظ كميات كبيرة من البيانات، الكتابة إلى Core Data أو نظام الملفات في viewWillDisappear يحجز الخيط الرئيسي. إذا استمرت العملية لفترة أطول من حركة الانتقال، يوقف UIKit الخيط وتتجمد الواجهة. أنقل العمليات الثقيلة إلى قوائم خلفية.
الخطأ الرابع — نسيان استدعاء super. عدم استدعاء super.viewWillDisappear يمكن أن يعطل UINavigationController و UITabBarController، اللذان يستخدمان هذه الطريقة لحالاتهما الداخلية. استدع دائمًا super أولًا أو أخيرًا، اتباعًا لتوثيق Apple.
تتفاقم هذه المشكلة في iOS مع تعدد المهام النشط والتبديل بين التطبيقات. الخطأ الخامس — استخدام DispatchQueue.main.async بعد الحفظ في viewWillDisappear. إذا قمت بإرسال كتلة بشكل غير متزامن إلى القائمة الرئيسية بعد استدعاء super.viewWillDisappear، فلا يوجد ضمان بأن المتحكم ما زال موجودًا عند تنفيذ الكتلة. استخدم دائمًا مراجع ضعيفة [weak self] داخل الإغلاقات لمنع الوصول إلى ذاكرة ملغاة ومنع تعطل التطبيق.
الأسئلة الشائعة
viewWillDisappear تتم استدعاؤها في بداية الاختفاء عندما تكون الشاشة ما زالت مرئية. viewDidDisappear تتم استدعاؤها بعد أن تكون الشاشة مخفية تمامًا واكتملت الحركة.
استخدم viewDidDisappear لتأكيد الحفظ أو تحقق من خصائص isMovingFromParent و isBeingDismissed داخل viewWillDisappear لتحديد ما إذا كانت الشاشة ستختفي فعلًا.
نعم، بالتأكيد إذا كنت تستخدم كتل أو محددات مع self. ARC لا يدير اشتراكات NotificationCenter. في iOS 9+ للكتل، استخدم مرجعًا ضعيفًا وألغ الاشتراك في viewWillDisappear.
بأي حال — force quit لا يستدعي طرق دورة الحياة. للحفظ المضمون عند إنهاء التطبيق، استخدم UIApplication.willTerminateNotification أو احفظ البيانات في الوقت الحقيقي عندما تتغير.
نعم، عند إيماء pop تفاعلي يستدعي UIKit viewWillDisappear فور بدء الإيماء. إذا ألغى المستخدم الإيماء، تبقى الشاشة مرئية ولكن الطريقة قد نشطت بالفعل. تحقق دائمًا من isMovingFromParent.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.