viewDidLoad في iOS: ما هو، الغرض منه وأمثلة كود

المؤلف: IT Sectr نُشر: 2026-03-05 وقت القراءة: 8 دق

viewDidLoad هو أول طريقة يستدعيها UIKit بعد تحميل View الخاصة بـ UIViewController في الذاكرة. وفقاً لـ Apple Developer Documentation، يتم استدعاء هذه الطريقة مرة واحدة فقط طوال عمر الـ controller. viewDidLoad هو المكان الرئيسي للإعداد الأولي للواجهة، وتسجيل الخلايا، وتهيئة البيانات.

الرئيسية

  • viewDidLoad يُستدعى مرة واحدة بعد تحميل View في الذاكرة
  • super.viewDidLoad إلزامي — بدونه ينهار Lifecycle
  • في هذه الطريقة يتم ضبط UI، وتسجيل الخلايا، وإنشاء data source
  • لا يُستدعى مرة أخرى عند العودة للشاشة — استخدم viewWillAppear
  • مناسب للعمليات للمرة الواحدة والاشتراك في الإشعارات الدائمة

ما هو viewDidLoad

viewDidLoad هو طريقة تابعة لـ UIViewController يستدعيها UIKit فور تحميل View الخاصة بـ controller في الذاكرة. في هذه المرحلة، تكون جميع خصائص IBOutlet متصلة بعناصر الواجهة، لكن View لم تُضف بعد إلى التسلسل الهرمي للنوافذ وليست مرئية للمستخدم. يقوم المطور بتجاوز هذه الطريقة لتنفيذ الإعداد الأولي للشاشة.

الطريقة هي جزء من ViewController Lifecycle وتأتي مباشرة بعد loadView إذا تم إنشاء View برمجياً، أو بعد التحميل من Storyboard. في مشروع نموذجي، viewDidLoad هو الطريقة الأكثر تجاوزاً في UIViewController، لأنه يوفر نقطة آمنة للعمل مع subviews الموجودة بالفعل والجاهزة للإعداد.

تفصيل مهم: عند استدعاء viewDidLoad، فإن أبعاد View لا تتوافق بعد مع الأبعاد النهائية — لم يكمل Auto Layout تمريراته، وقد يختلف الإطار (frame) عن المتوقع. للحسابات التي تعتمد على الأبعاد، استخدم viewDidLayoutSubviews.

متى يُستدعى viewDidLoad

توقيت استدعاء viewDidLoad يعتمد على كيفية تهيئة الـ controller. في معظم الحالات، يستدعي UIKit هذه الطريقة تلقائياً عند أول وصول إلى خاصية view الخاصة بـ controller — وهذا يُسمى آلية التحميل البطيء (lazy-loading) لـ UIViewController.

عند أول ظهور للشاشة

عندما يعرض NavigationController أو TabBarController شاشتك لأول مرة، يتحقق UIKit مما إذا كانت View محملة. إذا لم تكن — يتم استدعاء loadView (أو التحميل من Storyboard)، وبعدها يتم تشغيل viewDidLoad فوراً. هذا هو السيناريو القياسي، ويحدث مرة واحدة لكل نسخة من الـ controller.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    print("View تم تحميلها — يمكنك ضبط الواجهة")
    setupUI()
    configureTableView()
}

عند العودة إلى شاشة موجودة

viewDidLoad لا يُستدعى مرة أخرى عند العودة إلى الشاشة عبر زر الرجوع أو dismiss. إذا كان منطقك يعتمد على ظهور الشاشة مرة أخرى — ضعه في viewWillAppear. هذا من أكثر الأخطاء المفاهيمية شيوعاً: يتوقع المطورون أن viewDidLoad سيشتغل في كل عرض، لكن UIKit يستدعيه مرة واحدة فقط.

في forcedViewLoad

أحياناً يقوم المطورون بالوصول القسري إلى view الخاصة بـ controller لتفعيل التحميل مسبقاً: let _ = controller.view. هذا يجبر loadView و viewDidLoad على الاستدعاء قبل ظهور الـ controller على الشاشة. تُستخدم هذه التقنية عندما تحتاج إلى تحضير View مسبقاً لانتقال سلس.

ماذا تفعل في viewDidLoad

viewDidLoad مصمم لعمليات الإعداد لمرة واحدة التي لا تعتمد على ما إذا كانت الشاشة مرئية. الاستخدام الصحيح لهذه الطريقة هو مفتاح المعمارية النظيفة والسلوك المتوقع للـ controller.

ضبط مكونات UI

في viewDidLoad، يتم تسجيل ملفات nib والكلاسات الخاصة بـ UITableView و UICollectionView، وضبط الـ delegates، وتعيين القيم الأولية لخصائص عناصر UI. نظراً لأن جميع IBOutlet متصلة بالفعل في هذه المرحلة، يمكن الوصول بأمان إلى label.text و imageView.image وخصائص subview الأخرى.

swift
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

ليست كل العمليات مناسبة في 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

دعنا نلقي نظرة على ثلاثة أمثلة عملية توضح الاستخدام الصحيح لـ viewDidLoad في مشاريع حقيقية. كل مثال يحل مهمة محددة لتهيئة الشاشة.

مثال 1: ضبط مجموعة مع خلايا مخصصة

swift
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()
}

مثال 2: ضبط القيود (constraints) برمجياً

swift
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)
    ])
}

مثال 3: ضبط الحالة الفارغة واللودر

في viewDidLoad أيضاً يتم ضبط العناصر المعروضة عند عدم وجود بيانات: الحالة الفارغة، اللودر، placeholder. يتم إنشاء هذه المكونات مرة واحدة وتُعاد استخدامها في كل مرة تظهر فيها الشاشة. إخفاء أو إظهار هذه العناصر يُدار في viewWillAppear حسب البيانات الحالية.

swift
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)
}

مثال 4: الاشتراك في إشعارات التطبيق

swift
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleEnterForeground),
        name: UIApplication.willEnterForegroundNotification,
        object: nil
    )
}

@objc private func handleEnterForeground() {
    refreshContent()
}

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

هل يمكن استدعاء viewDidLoad أكثر من مرة؟

في الظروف العادية، لا — UIKit يستدعي viewDidLoad مرة واحدة بعد تحميل View في الذاكرة. إذا تم تدمير الـ controller وإنشاؤه من جديد، فسيشتغل viewDidLoad للنسخة الجديدة.

هل أحتاج لاستدعاء super.viewDidLoad؟

نعم، بالتأكيد. استدعاء super.viewDidLoad يضمن أن UIKit ينفذ الإعداد الداخلي اللازم لعمل Lifecycle بشكل صحيح. استدعِ super دائماً في بداية الطريقة.

ما الفرق بين viewDidLoad و viewWillAppear؟

viewDidLoad يُستدعى مرة واحدة عند تحميل View. viewWillAppear يُستدعى كل مرة قبل ظهور الشاشة. الأول للإعداد لمرة واحدة، والثاني لتحديث البيانات والحالة.

هل يمكن تنفيذ عمليات ثقيلة في viewDidLoad؟

العمليات المتزامنة الثقيلة في viewDidLoad تمنع الخيط الرئيسي وتؤخر ظهور الشاشة. التحميل غير المتزامن مقبول، لكن عند تحديث UI بعد الاكتمال يجب مراعاة أن الشاشة قد تكون مخفية بالفعل.

كيف أفرض استدعاء viewDidLoad؟

لا يمكن استدعاء viewDidLoad مباشرة — UIKit يستدعيه. لفرض تحميل View، قم بالوصول إلى الخاصية controller.view. هذا سيطلق loadView و viewDidLoad تلقائياً.

الخلاصة

  • viewDidLoad هو طريقة إعداد لمرة واحدة لـ UIViewController تُستدعى بعد تحميل View في الذاكرة
  • يُستدعى مرة واحدة طوال عمر الـ controller عند أول وصول إلى View
  • مناسب لتسجيل الخلايا، وضبط الـ delegates، وتهيئة viewModel
  • استدعِ دائماً super.viewDidLoad لضمان عمل Lifecycle بشكل صحيح
  • لا تستخدم viewDidLoad للعمليات التي تعتمد على أبعاد View
  • لتحديث البيانات في كل ظهور، استخدم viewWillAppear
  • الاشتراك في الإشعارات الدائمة مناسب، والمؤقتة — في viewWillAppear

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا