viewDidLoad هو أول طريقة يستدعيها UIKit بعد تحميل View الخاصة بـ UIViewController في الذاكرة. وفقاً لـ Apple Developer Documentation، يتم استدعاء هذه الطريقة مرة واحدة فقط طوال عمر الـ controller. viewDidLoad هو المكان الرئيسي للإعداد الأولي للواجهة، وتسجيل الخلايا، وتهيئة البيانات.
الرئيسية
viewDidLoad هو طريقة تابعة لـ UIViewController يستدعيها UIKit فور تحميل View الخاصة بـ controller في الذاكرة. في هذه المرحلة، تكون جميع خصائص IBOutlet متصلة بعناصر الواجهة، لكن View لم تُضف بعد إلى التسلسل الهرمي للنوافذ وليست مرئية للمستخدم. يقوم المطور بتجاوز هذه الطريقة لتنفيذ الإعداد الأولي للشاشة.
الطريقة هي جزء من ViewController Lifecycle وتأتي مباشرة بعد loadView إذا تم إنشاء View برمجياً، أو بعد التحميل من Storyboard. في مشروع نموذجي، viewDidLoad هو الطريقة الأكثر تجاوزاً في UIViewController، لأنه يوفر نقطة آمنة للعمل مع subviews الموجودة بالفعل والجاهزة للإعداد.
تفصيل مهم: عند استدعاء viewDidLoad، فإن أبعاد View لا تتوافق بعد مع الأبعاد النهائية — لم يكمل Auto Layout تمريراته، وقد يختلف الإطار (frame) عن المتوقع. للحسابات التي تعتمد على الأبعاد، استخدم viewDidLayoutSubviews.
توقيت استدعاء viewDidLoad يعتمد على كيفية تهيئة الـ controller. في معظم الحالات، يستدعي UIKit هذه الطريقة تلقائياً عند أول وصول إلى خاصية view الخاصة بـ controller — وهذا يُسمى آلية التحميل البطيء (lazy-loading) لـ UIViewController.
عندما يعرض NavigationController أو TabBarController شاشتك لأول مرة، يتحقق UIKit مما إذا كانت View محملة. إذا لم تكن — يتم استدعاء loadView (أو التحميل من Storyboard)، وبعدها يتم تشغيل viewDidLoad فوراً. هذا هو السيناريو القياسي، ويحدث مرة واحدة لكل نسخة من الـ controller.
override func viewDidLoad() {
super.viewDidLoad()
print("View تم تحميلها — يمكنك ضبط الواجهة")
setupUI()
configureTableView()
}
viewDidLoad لا يُستدعى مرة أخرى عند العودة إلى الشاشة عبر زر الرجوع أو dismiss. إذا كان منطقك يعتمد على ظهور الشاشة مرة أخرى — ضعه في viewWillAppear. هذا من أكثر الأخطاء المفاهيمية شيوعاً: يتوقع المطورون أن viewDidLoad سيشتغل في كل عرض، لكن UIKit يستدعيه مرة واحدة فقط.
أحياناً يقوم المطورون بالوصول القسري إلى view الخاصة بـ controller لتفعيل التحميل مسبقاً: let _ = controller.view. هذا يجبر loadView و viewDidLoad على الاستدعاء قبل ظهور الـ controller على الشاشة. تُستخدم هذه التقنية عندما تحتاج إلى تحضير View مسبقاً لانتقال سلس.
viewDidLoad مصمم لعمليات الإعداد لمرة واحدة التي لا تعتمد على ما إذا كانت الشاشة مرئية. الاستخدام الصحيح لهذه الطريقة هو مفتاح المعمارية النظيفة والسلوك المتوقع للـ controller.
في viewDidLoad، يتم تسجيل ملفات nib والكلاسات الخاصة بـ UITableView و UICollectionView، وضبط الـ delegates، وتعيين القيم الأولية لخصائص عناصر UI. نظراً لأن جميع IBOutlet متصلة بالفعل في هذه المرحلة، يمكن الوصول بأمان إلى label.text و imageView.image وخصائص subview الأخرى.
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.register(
CustomCell.self,
forCellReuseIdentifier: CustomCell.identifier
)
title = "الشاشة الرئيسية"
}
هنا يتم إنشاء viewModel، وتهيئة data source بالمصفوفات، والاشتراك في الإشعارات التي يجب أن تكون نشطة طوال عمر الـ controller. على سبيل المثال، الاشتراك في UIApplication.willEnterForegroundNotification لتحديث البيانات عند العودة من الخلفية هو مرشح جيد لـ viewDidLoad. viewModel في معمارية iOS الحديثة تعمل كجسر بين الـ controller ومنطق الأعمال، وتهيئتها في viewDidLoad تضمن جاهزية البيانات عند أول ظهور للشاشة.
انتبه بشكل خاص لضبط data source للجداول والمجموعات. إذا كان جدولك يستخدم UIFetchedResultsController أو NSFetchedResultsController مع Core Data، قم بتهيئة fetch request والـ delegate في viewDidLoad. هذا يضمن أنه عند أول ظهور للشاشة، سيكون الجدول ممتلئاً بالبيانات دون طلبات إضافية.
في viewDidLoad، يتم ضبط أزرار NavigationBar، وتعيين large title، وإضافة search controller، وتعيين أزرار edit/done. هذه العناصر نادراً ما تتغير عند إعادة عرض الشاشة، لذلك تهيئتها هنا أمثل.
ليست كل العمليات مناسبة في viewDidLoad. بعض الإجراءات الموضوعة في هذه الطريقة تؤدي إلى استهلاك مفرط للذاكرة، أو سلوك غير صحيح، أو أخطاء عند إعادة عرض الشاشة.
تجنب بدء طلبات الشبكة التي تؤثر نتائجها فقط على UI. إذا اكتمل الطلب قبل ظهور الشاشة، لن يرى المستخدم النتيجة، وإذا اكتمل بعد ذلك — فقد تكون البيانات قديمة. ابدأ التحميل في viewDidLoad، لكن حدّث UI في viewWillAppear.
لا تقم بعمليات في viewDidLoad تعتمد على حجم وموقع View. في وقت الاستدعاء، لم يكمل Auto Layout تمريراته، وقد لا يكون الإطار (frame) نهائياً. للحسابات، استخدم viewDidLayoutSubviews أو تجاوز updateViewConstraints.
لا تشترك في إشعارات ذات صلة فقط عندما تكون الشاشة مرئية. إشعارات لوحة المفاتيح، إشعارات تغيير المحتوى من controllers فرعية — اشترك فيها في viewWillAppear وألغِ الاشتراك في viewDidDisappear لتجنب الاستدعاءات غير الضرورية والتسريبات.
لا تستدعِ طرقاً تتطلب شاشة مرئية. على سبيل المثال، محاولة عرض UIAlertController من viewDidLoad ستؤدي إلى خطأ لأن View الخاصة بـ controller لم تُضف بعد إلى التسلسل الهرمي للنوافذ. أي عمليات UI تعتمد على النافذة أو presentedViewController يجب أن تُنفذ فقط بعد ظهور الشاشة.
لا تهِئ موارد ثقيلة بدون داعٍ. إذا كانت الشاشة تُعرض نادراً أو لا تُعرض البيانات فوراً، أرجئ إنشاء الكائنات كثيفة الاستخدام للموارد حتى الحاجة الفعلية إليها. التهيئة البطيئة (lazy initialization) للخصائص في Swift هي آلية مدمجة لحل هذه المشكلة: الخاصية مع معدّل lazy سيتم إنشاؤها فقط عند أول وصول إليها، مما يوفر الذاكرة ويسرّع تحميل الشاشة.
لا تستخدم viewDidLoad للعمليات التي يجب تنفيذها في كل مرة تظهر فيها الشاشة. هذا هو الخطأ الأكثر جوهرية: المطورون المبتدئون غالباً ما يضعون منطق تحديث البيانات في viewDidLoad ويتفاجؤون أنه عند العودة من شاشة أخرى، لا يتم إعادة تحميل الجدول. إذا كان يجب تكرار العملية في كل عرض — استخدم viewWillAppear. إذا كان يجب تنفيذها مرة واحدة طوال العمر — استخدم viewDidLoad. تذكر هذه القاعدة البسيطة لتجنب معظم مشاكل دورة حياة UIViewController.
دعنا نلقي نظرة على ثلاثة أمثلة عملية توضح الاستخدام الصحيح لـ viewDidLoad في مشاريع حقيقية. كل مثال يحل مهمة محددة لتهيئة الشاشة.
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(
PhotoCell.self,
forCellWithReuseIdentifier: PhotoCell.reuseId
)
collectionView.register(
HeaderView.self,
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: HeaderView.reuseId
)
viewModel.delegate = self
viewModel.fetchInitialPage()
}
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
label.text = "مرحباً بالعالم!"
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
في viewDidLoad أيضاً يتم ضبط العناصر المعروضة عند عدم وجود بيانات: الحالة الفارغة، اللودر، placeholder. يتم إنشاء هذه المكونات مرة واحدة وتُعاد استخدامها في كل مرة تظهر فيها الشاشة. إخفاء أو إظهار هذه العناصر يُدار في viewWillAppear حسب البيانات الحالية.
override func viewDidLoad() {
super.viewDidLoad()
emptyStateLabel = UILabel()
emptyStateLabel.text = "لا توجد بيانات"
emptyStateLabel.textAlignment = .center
emptyStateLabel.isHidden = true
view.addSubview(emptyStateLabel)
activityIndicator = UIActivityIndicatorView(style: .medium)
activityIndicator.hidesWhenStopped = true
view.addSubview(activityIndicator)
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(handleEnterForeground),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
}
@objc private func handleEnterForeground() {
refreshContent()
}
الأسئلة الشائعة
في الظروف العادية، لا — UIKit يستدعي viewDidLoad مرة واحدة بعد تحميل View في الذاكرة. إذا تم تدمير الـ controller وإنشاؤه من جديد، فسيشتغل viewDidLoad للنسخة الجديدة.
نعم، بالتأكيد. استدعاء super.viewDidLoad يضمن أن UIKit ينفذ الإعداد الداخلي اللازم لعمل Lifecycle بشكل صحيح. استدعِ super دائماً في بداية الطريقة.
viewDidLoad يُستدعى مرة واحدة عند تحميل View. viewWillAppear يُستدعى كل مرة قبل ظهور الشاشة. الأول للإعداد لمرة واحدة، والثاني لتحديث البيانات والحالة.
العمليات المتزامنة الثقيلة في viewDidLoad تمنع الخيط الرئيسي وتؤخر ظهور الشاشة. التحميل غير المتزامن مقبول، لكن عند تحديث UI بعد الاكتمال يجب مراعاة أن الشاشة قد تكون مخفية بالفعل.
لا يمكن استدعاء viewDidLoad مباشرة — UIKit يستدعيه. لفرض تحميل View، قم بالوصول إلى الخاصية controller.view. هذا سيطلق loadView و viewDidLoad تلقائياً.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.