ViewController — ماهیت، کنترل‌کننده صفحه در iOS و چرخه حیات آن

نویسنده: IT Sectr منتشر شده: 2026-02-22 زمان مطالعه: 7 دقیقه

UIViewController — کلاس مرکزی برنامه iOS، مدیریت صفحه و محتوای آن. هر صفحه از iPhone یا iPad توسط یک ViewController مدیریت می‌شود که نمایش، چرخه حیات و ناوبری را هماهنگ می‌کند. جزئیات بیشتر درباره معماری UIKit را در مستندات رسمی Apple بخوانید.

نکات اصلی

  • UIViewController — کلاس پایه برای مدیریت صفحه در UIKit با چرخه حیات اختصاصی
  • viewDidLoad — یک بار فراخوانی می‌شود، نقطه مقداردهی اولیه UI و اشتراک داده
  • 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یک بار، پس از بارگذاری view در حافظهتنظیم اولیه UI، اشتراک Combine
viewWillAppearقبل از ظاهر شدن صفحهبه‌روزرسانی داده، مخفی/نمایش نوار ناوبری
viewDidAppearپس از ظاهر شدن صفحهراه‌اندازی انیمیشن‌ها، تحلیل، به‌روزرسانی دوربین
viewWillDisappearقبل از خروج از صفحهذخیره پیش‌نویس‌ها، لغو اشتراک اعلان‌ها
viewDidDisappearپس از خروج از صفحهتوقف فرآیندهای سنگین، آزادسازی منابع

ترتیب فراخوانی هنگام ظاهر شدن صفحه

در اولین نمایش صفحه دنباله: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. در ظاهر شدن مجدد (بازگشت از صفحه دیگر): viewWillAppear → viewDidAppear. viewDidLoad فقط یک بار در طول عمر کنترل‌کننده فراخوانی می‌شود.

viewDidLoad، init و تنظیم UI

روش viewDidLoad — نقطه اصلی تنظیم رابط کاربری. پس از بارگذاری view در حافظه فراخوانی می‌شود، زمانی که همه IBOutlet‌ها متصل شده‌اند. در اینجا عناصر UI به صورت برنامه‌نویسی ایجاد شده، محدودیت‌ها تنظیم و داده‌های اولیه بارگذاری می‌شوند.

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 (master-detail برای 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، افزودن view و didMove(toParent:) به این ترتیب است. هنگام حذف — willMove(toParent: nil)، removeFromSuperview، removeFromParent. نقض ترتیب منجر به نشت حافظه می‌شود.

حل Massive View Controller با MVVM و Coordinator

مشکل Massive View Controller — زمانی که UIViewController حاوی صدها خط کد با منطق تجاری، درخواست‌های شبکه، ناوبری و کد UI است. Apple از مشکل آگاه است و MVVM (Model-View-ViewModel) را همراه با Coordinator برای جداسازی ناوبری توصیه می‌کند.

MVVM منطق تجاری را از کنترل‌کننده به ViewModel منتقل می‌کند. Controller فقط ViewModel را از طریق Combine یا delegate به View متصل می‌کند. Coordinator منطق ناوبری — ایجاد و انتقال بین کنترل‌کننده‌ها — را به یک کلاس جداگانه منتقل می‌کند. این رویکرد از سال 2024 وارد بهترین شیوه‌های Apple شده است.

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
سرعت توسعهکندتر (layout دستی)سریعتر (اعلامی)

سوالات متداول

تفاوت UIViewController با UIView چیست؟

UIViewController — کنترل‌کننده‌ای که صفحه و چرخه حیات آن را مدیریت می‌کند. UIView — نمایی که محتوا را نمایش می‌دهد. ViewController شامل سلسله‌مراتب UIView است اما خود عنصر بصری نیست. یک کنترل‌کننده بسیاری از نماها را مدیریت می‌کند.

Massive View Controller چیست؟

Massive View Controller — ضدالگویی که در آن UIViewController منطق زیادی شامل داده‌ها، ناوبری، درخواست‌های شبکه و انیمیشن‌ها را در خود دارد. راه‌حل — جداسازی کد به سرویس‌های جداگانه، هماهنگ‌کننده‌ها و ViewModel (MVVM).

چگونه داده را بین ViewControllerها منتقل کنیم؟

چهار روش: از طریق ویژگی در prepare(for:sender:) (Segue)، از طریق Delegate، از طریق Closure، از طریق سرویس مشترک. برای اتصال ضعیف از Coordinator + Delegate یا Combine استفاده می‌شود.

Container View Controller چیست؟

Container View Controller — کنترل‌کننده‌ای که ViewControllerهای زیردست را مدیریت می‌کند. مثال‌ها: UINavigationController، UITabBarController، UISplitViewController. کنترل‌کننده والد زیردستان را از طریق addChild اضافه می‌کند، بین آنها جابجا می‌شود و layout آنها را مدیریت می‌کند.

چه زمانی از UIViewController به جای SwiftUI View استفاده کنیم؟

UIViewController — برای انیمیشن سفارشی پیچیده، کار با دوربین، نقشه، ویدئو، UICollectionView با layout سفارشی. SwiftUI View — برای رابط‌های استاندارد iOS 13+. ترکیب از طریق UIHostingController مجاز است.

خلاصه

  • UIViewController — کلاس مرکزی UIKit برای مدیریت صفحه، سلسله‌مراتب UIView و چرخه حیات
  • چرخه حیات شامل پنج روش: viewDidLoad، viewWillAppear، viewDidAppear، viewWillDisappear، viewDidDisappear
  • viewDidLoad — نقطه تنظیم اولیه UI، یک بار در طول عمر کنترل‌کننده فراخوانی می‌شود
  • viewWillAppear — هر بار قبل از نمایش فراخوانی می‌شود، مناسب برای به‌روزرسانی داده و تنظیم نوار ناوبری
  • Container View Controller (UINavigationController، UITabBarController) سلسله‌مراتب کنترل‌کننده‌های زیردست را مدیریت می‌کند
  • Massive View Controller از طریق MVVM (جداسازی منطق به ViewModel) و Coordinator (جداسازی ناوبری) حل می‌شود
  • UIViewController و SwiftUI را می‌توان از طریق UIHostingController و UIViewRepresentable برای برنامه‌های ترکیبی متصل کرد

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید