ViewController — جوهر وحدة التحكم في الشاشة في iOS ودورة حياتها

المؤلف: IT Sectr نُشر: 2026-02-22 وقت القراءة: 7 دق

UIViewController هي الفئة المركزية لتطبيقات iOS، التي تدير الشاشة ومحتوياتها. كل شاشة iPhone أو iPad تُدار بواسطة ViewController واحد، ينسق العرض ودورة الحياة والتنقل. اقرأ المزيد عن بنية UIKit في الوثائق الرسمية لـ Apple.

النقاط الرئيسية

  • UIViewController — الفئة الأساسية لإدارة شاشة في UIKit مع دورة حياة خاصة بها
  • viewDidLoad — يُستدعى مرة واحدة، نقطة تهيئة واجهة المستخدم والاشتراك في البيانات
  • viewWillAppear — ستظهر الشاشة قريباً، تحديث البيانات قبل العرض
  • دورة الحياة تتضمن خمس طرق: viewDidLoad وviewWillAppear وviewDidAppear وviewWillDisappear وviewDidDisappear
  • Massive View Controller — النمط المعاكس الرئيسي في iOS، يُحل بواسطة MVVM أو Coordinator

ما هو ViewController؟

UIViewController هي فئة من إطار عمل UIKit تدير تسلسلاً هرمياً لـ UIView وتنسق عرض البيانات على الشاشة. كل تطبيق iOS يحتوي على ViewController واحد على الأقل — وحدة التحكم الجذرية للنافذة. تتعامل وحدة التحكم مع تدوير الشاشة والانتقالات بين الشاشات وأحداث دورة الحياة.

بنية MVC (Model-View-Controller) في iOS تُنفذ تحديداً عبر UIViewController: تتلقى وحدة التحكم البيانات من النموذج وتحدّث العرض. ViewController ليس عنصراً مرئياً — فهو يدير الخاصية view التي تحتوي على تسلسل هرمي من subview. وفقاً لـ Apple (2026)، يحتوي UIKit على أكثر من 40 فئة فرعية مدمجة من UIViewController.

أول iPhone SDK (2008) تضمن UIViewController مع ثلاث طرق لدورة الحياة. على مدى 18 عاماً، أضافت Apple دعماً لـ Container View Controller والعروض التكيفية وUIViewControllerTransitioningDelegate للرسوم المتحركة المخصصة ووضع الشاشة المقسمة على iPad. UIViewController لا يزال مكوناً إلزامياً لتطبيقات UIKit.

دورة حياة UIViewController

دورة حياة UIViewController هي سلسلة من الطرق التي يستدعيها النظام عند إنشاء شاشة وعرضها وإخفائها. فهم دورة الحياة أمر بالغ الأهمية: وضع الكود بشكل غير صحيح يؤدي إلى تسرب الذاكرة وطلبات شبكة غير ضرورية ووميض في الواجهة.

الطريقةلحظة الاستدعاءالغرض
viewDidLoadمرة واحدة، بعد تحميل العرض في الذاكرةإعداد واجهة المستخدم الأولي، الاشتراك في Combine
viewWillAppearقبل ظهور الشاشةتحديث البيانات، إخفاء/إظهار شريط التنقل
viewDidAppearبعد ظهور الشاشةبدء الرسوم المتحركة، التحليلات، تحديث الكاميرا
viewWillDisappearقبل مغادرة الشاشةحفظ المسودات، إلغاء الاشتراك في الإشعارات
viewDidDisappearبعد مغادرة الشاشةإيقاف العمليات الثقيلة، تحرير الموارد

ترتيب الاستدعاء عند ظهور الشاشة

في أول عرض للشاشة، التسلسل هو: init ← loadView ← viewDidLoad ← viewWillAppear ← viewDidAppear. عند الظهور مرة أخرى (العودة من شاشة أخرى): viewWillAppear ← viewDidAppear. viewDidLoad يُستدعى مرة واحدة فقط طوال عمر وحدة التحكم.

viewDidLoad وinit وإعداد واجهة المستخدم

طريقة viewDidLoad هي النقطة الرئيسية لإعداد واجهة المستخدم. تُستدعى بعد تحميل العرض في الذاكرة، عندما تكون جميع اتصالات IBOutlet قد تم ربطها بالفعل. هنا تُنشأ عناصر واجهة المستخدم برمجياً، وتُضبط القيود (constraints)، وتُحمل البيانات الأولية.

swift
final class ProfileViewController: UIViewController {

    private let tableView = UITableView()
    private let viewModel = ProfileViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        bindViewModel()
    }

    private func setupUI() {
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        tableView.register(ProfileCell.self,
                         forCellReuseIdentifier: ProfileCell.reuseId)
    }

    private func bindViewModel() {
        viewModel.$user
            .receive(on: DispatchQueue.main)
            .sink { [weak self] user in
                self?.title = user.name
            }
            .store(in: &cancellables)
    }
}

في SwiftUI، هذا الكود يعادل جسم View. لكن UIViewController يمنح تحكماً كاملاً في دورة الحياة والتحسين. bindViewModel يستخدم Combine للاشتراك التفاعلي — يتم تحديث البيانات تلقائياً عندما يتغير النموذج.

viewWillAppear وتحديث البيانات

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

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // إخفاء شريط التنقل في هذه الشاشة
    navigationController?.setNavigationBarHidden(true, animated: animated)

    // تحديث البيانات عند العودة من شاشة أخرى
    tableView.reloadData()
    badgeLabel.text = "\(CartManager.shared.itemCount)"
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // التحليلات: فقط بعد أن رأى المستخدم الشاشة
    AnalyticsService.shared.logScreenView("Profile")
}

الفرق بين viewDidLoad وviewWillAppear جوهري: viewDidLoad يُنفذ مرة واحدة ومناسب للإعداد الثابت، viewWillAppear يُنفذ في كل مرة تُعرض فيها الشاشة ومناسب للتحديثات الديناميكية. وضع طلبات الشبكة في viewDidLoad سيؤدي إلى عرض بيانات قديمة عند العودة إلى الشاشة.

Container View Controller: UINavigationController وUITabBarController

Container View Controller هو ViewController يدير ViewController فرعياً واحداً أو أكثر. توفر Apple ثلاثة حاويات مدمجة: UINavigationController (كومة شاشات)، UITabBarController (علامات تبويب)، وUISplitViewController (سيد-تفصيل لـ iPad).

UINavigationController ينظم الانتقالات في كومة — push يضيف شاشة، pop يزيلها. UITabBarController يتبدل بين الأقسام المستقلة للتطبيق. UISplitViewController يعرض وحدتي تحكم جنباً إلى جنب على iPad وواحدة على iPhone. يمكن للمطور إنشاء حاوية مخصصة عبر addChild.

swift
// Container View Controller مخصص
final class ContainerViewController: UIViewController {

    private let sidebarVC = SidebarViewController()
    private let contentVC = ContentViewController()

    override func viewDidLoad() {
        super.viewDidLoad()

        // إضافة وحدة تحكم فرعية
        addChild(sidebarVC)
        view.addSubview(sidebarVC.view)
        sidebarVC.didMove(toParent: self)

        addChild(contentVC)
        view.addSubview(contentVC.view)
        contentVC.didMove(toParent: self)
    }
}

العمل الصحيح مع Container View Controller يتطلب استدعاء addChild وإضافة العرض وdidMove(toParent:) بهذا الترتيب. عند الإزالة: willMove(toParent: nil) وremoveFromSuperview وremoveFromParent. مخالفة التسلسل تؤدي إلى تسرب الذاكرة.

حل Massive View Controller باستخدام MVVM وCoordinator

مشكلة Massive View Controller تحدث عندما يحتوي UIViewController على مئات الأسطر من الكود مع منطق الأعمال وطلبات الشبكة والتنقل وكود واجهة المستخدم. تدرك Apple المشكلة وتوصي بـ MVVM (Model-View-ViewModel) مع Coordinator لإخراج التنقل.

MVVM ينقل منطق الأعمال من وحدة التحكم إلى ViewModel. Controller فقط يربط ViewModel بـ View عبر Combine أو المفوض. Coordinator يستخرج منطق التنقل — إنشاء والانتقال بين وحدات التحكم — في فئة منفصلة. تم اعتماد هذا النهج في أفضل ممارسات Apple منذ 2024.

swift
// Coordinator — إدارة التنقل
protocol Coordinator {
    var childCoordinators: [Coordinator] { get set }
    func start()
}

final class MainCoordinator: Coordinator {

    var childCoordinators = [Coordinator]()
    private let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() {
        let vc = ListViewController()
        vc.didSelectItem = { [weak self] item in
            self?.showDetail(item)
        }
        navigationController.pushViewController(vc, animated: false)
    }

    private func showDetail(_ item: Item) {
        let vc = DetailViewController(item: item)
        navigationController.pushViewController(vc, animated: true)
    }
}

UIViewController مقابل SwiftUI: متى تختار ماذا

الاختيار بين UIViewController وSwiftUI View يعتمد على سنة بدء المشروع ومتطلبات التخصيص والحد الأدنى من إصدار iOS المدعوم. يبقى UIKit مع UIViewController الأساس للمشاريع التي بدأت قبل 2020 وللتطبيقات ذات التخصيص العميق للواجهة.

SwiftUI مناسب للمشاريع الجديدة مع iOS 17+ والواجهات القياسية والنماذج الأولية. ومع ذلك، تتطلب الانتقالات المخصصة والعمل مع الكاميرا وMapKit والرسوم المتحركة المعقدة لـ CALayer استخدام UIViewController. توصي Apple بالجمع بين النهجين عبر UIHostingController (SwiftUI داخل UIKit) وUIViewRepresentable (UIKit داخل SwiftUI).

السيناريوUIKit (UIViewController)SwiftUI (View)
رسوم متحركة مخصصةتحكم كامل عبر UIViewPropertyAnimatorمحدود عبر Animation
العمل مع الكاميراAVCaptureSession + UIViewPreviewعبر UIViewControllerRepresentable
CollectionViewUICollectionView + UICollectionViewLayoutLazyVGrid/LazyHGrid
تكيف iPadUISplitViewController + UITraitCollectionNavigationSplitView + sizeClass
سرعة التطويرأبطأ (تخطيط يدوي)أسرع (تصريحي)

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

كيف يختلف UIViewController عن UIView؟

UIViewController هو وحدة تحكم تدير الشاشة ودورة حياتها. UIView هو عرض يعرض المحتوى. ViewController يحتوي على تسلسل هرمي من UIViews لكنه ليس عنصراً مرئياً بحد ذاته. وحدة تحكم واحدة تدير عروضاً متعددة.

ما هو Massive View Controller؟

Massive View Controller هو نمط معاكس حيث يحتوي UIViewController على الكثير من المنطق: البيانات والتنقل وطلبات الشبكة والرسوم المتحركة. الحل هو استخراج الكود إلى خدمات منفصلة ومنسقين وViewModel (MVVM).

كيفية نقل البيانات بين ViewControllers؟

أربع طرق: عبر خاصية في prepare(for:sender:) (Segue)، عبر مفوض (Delegate)، عبر إغلاق (Closure)، عبر خدمة مشتركة. للاقتران الضعيف، استخدم Coordinator + Delegate أو Combine.

ما هو Container View Controller؟

Container View Controller هو وحدة تحكم تدير ViewControllers فرعية. أمثلة: UINavigationController وUITabBarController وUISplitViewController. وحدة التحكم الأم تضيف أطفالاً عبر addChild وتتبدل بينهم وتدير تخطيطهم.

متى نستخدم UIViewController بدلاً من SwiftUI View؟

UIViewController — للرسوم المتحركة المخصصة المعقدة والعمل مع الكاميرا والخرائط والفيديو وUICollectionView مع تخطيط مخصص. SwiftUI View — للواجهات القياسية على iOS 13+. الجمع عبر UIHostingController مقبول.

الملخص

  • UIViewController — الفئة المركزية في UIKit لإدارة الشاشة والتسلسل الهرمي لـ UIView ودورة الحياة
  • دورة الحياة تتكون من خمس طرق: viewDidLoad وviewWillAppear وviewDidAppear وviewWillDisappear وviewDidDisappear
  • viewDidLoad — نقطة الإعداد الأولي لواجهة المستخدم، تُستدعى مرة واحدة طوال عمر وحدة التحكم
  • viewWillAppear — تُستدعى في كل مرة قبل العرض، مناسبة لتحديث البيانات وضبط شريط التنقل
  • Container View Controller (UINavigationController وUITabBarController) يدير التسلسل الهرمي لوحدات التحكم الفرعية
  • Massive View Controller يُحل عبر MVVM (استخراج المنطق إلى ViewModel) وCoordinator (استخراج التنقل)
  • UIViewController وSwiftUI يمكن دمجهما عبر UIHostingController وUIViewRepresentable للتطبيقات الهجينة

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

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

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

اقرأ أيضًا