UIViewController — کلاس مرکزی برنامه iOS، مدیریت صفحه و محتوای آن. هر صفحه از iPhone یا iPad توسط یک ViewController مدیریت میشود که نمایش، چرخه حیات و ناوبری را هماهنگ میکند. جزئیات بیشتر درباره معماری UIKit را در مستندات رسمی Apple بخوانید.
نکات اصلی
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 — دنبالهای از روشها که توسط سیستم هنگام ایجاد، نمایش و مخفیسازی صفحه فراخوانی میشوند. درک چرخه حیات بسیار حیاتی است: قرارگیری نادرست کد منجر به نشت حافظه، درخواستهای شبکه اضافی و سوسو زدن رابط میشود.
| روش | زمان فراخوانی | هدف |
|---|---|---|
| viewDidLoad | یک بار، پس از بارگذاری view در حافظه | تنظیم اولیه UI، اشتراک Combine |
| viewWillAppear | قبل از ظاهر شدن صفحه | بهروزرسانی داده، مخفی/نمایش نوار ناوبری |
| viewDidAppear | پس از ظاهر شدن صفحه | راهاندازی انیمیشنها، تحلیل، بهروزرسانی دوربین |
| viewWillDisappear | قبل از خروج از صفحه | ذخیره پیشنویسها، لغو اشتراک اعلانها |
| viewDidDisappear | پس از خروج از صفحه | توقف فرآیندهای سنگین، آزادسازی منابع |
در اولین نمایش صفحه دنباله: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. در ظاهر شدن مجدد (بازگشت از صفحه دیگر): viewWillAppear → viewDidAppear. viewDidLoad فقط یک بار در طول عمر کنترلکننده فراخوانی میشود.
روش viewDidLoad — نقطه اصلی تنظیم رابط کاربری. پس از بارگذاری view در حافظه فراخوانی میشود، زمانی که همه IBOutletها متصل شدهاند. در اینجا عناصر UI به صورت برنامهنویسی ایجاد شده، محدودیتها تنظیم و دادههای اولیه بارگذاری میشوند.
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 هر بار قبل از ظاهر شدن صفحه فراخوانی میشود، حتی اگر قبلاً در حافظه بوده باشد. این مکان برای بهروزرسانی دادههایی است که ممکن است در صفحه دیگر تغییر کرده باشند: بارگذاری مجدد لیست، بهروزرسانی شمارنده اعلانها، تنظیم نوار ناوبری برای صفحه خاص.
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 — ViewControllerای که یک یا چند ViewController زیردست را مدیریت میکند. Apple سه کانتینر داخلی ارائه میدهد: UINavigationController (پشته صفحه)، UITabBarController (زبانهها) و UISplitViewController (master-detail برای iPad).
UINavigationController انتقالها را به صورت پشته سازماندهی میکند — push صفحه اضافه میکند، pop حذف میکند. UITabBarController بین بخشهای مستقل برنامه جابجا میشود. UISplitViewController دو کنترلکننده را در iPad در کنار هم و در iPhone یکی را نشان میدهد. توسعهدهنده میتواند کانتینر خود را از طریق addChild ایجاد کند.
// 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 — زمانی که UIViewController حاوی صدها خط کد با منطق تجاری، درخواستهای شبکه، ناوبری و کد UI است. Apple از مشکل آگاه است و MVVM (Model-View-ViewModel) را همراه با Coordinator برای جداسازی ناوبری توصیه میکند.
MVVM منطق تجاری را از کنترلکننده به ViewModel منتقل میکند. Controller فقط ViewModel را از طریق Combine یا delegate به View متصل میکند. Coordinator منطق ناوبری — ایجاد و انتقال بین کنترلکنندهها — را به یک کلاس جداگانه منتقل میکند. این رویکرد از سال 2024 وارد بهترین شیوههای Apple شده است.
// 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 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 |
| CollectionView | UICollectionView + UICollectionViewLayout | LazyVGrid/LazyHGrid |
| سازگاری iPad | UISplitViewController + UITraitCollection | NavigationSplitView + sizeClass |
| سرعت توسعه | کندتر (layout دستی) | سریعتر (اعلامی) |
سوالات متداول
UIViewController — کنترلکنندهای که صفحه و چرخه حیات آن را مدیریت میکند. UIView — نمایی که محتوا را نمایش میدهد. ViewController شامل سلسلهمراتب UIView است اما خود عنصر بصری نیست. یک کنترلکننده بسیاری از نماها را مدیریت میکند.
Massive View Controller — ضدالگویی که در آن UIViewController منطق زیادی شامل دادهها، ناوبری، درخواستهای شبکه و انیمیشنها را در خود دارد. راهحل — جداسازی کد به سرویسهای جداگانه، هماهنگکنندهها و ViewModel (MVVM).
چهار روش: از طریق ویژگی در prepare(for:sender:) (Segue)، از طریق Delegate، از طریق Closure، از طریق سرویس مشترک. برای اتصال ضعیف از Coordinator + Delegate یا Combine استفاده میشود.
Container View Controller — کنترلکنندهای که ViewControllerهای زیردست را مدیریت میکند. مثالها: UINavigationController، UITabBarController، UISplitViewController. کنترلکننده والد زیردستان را از طریق addChild اضافه میکند، بین آنها جابجا میشود و layout آنها را مدیریت میکند.
UIViewController — برای انیمیشن سفارشی پیچیده، کار با دوربین، نقشه، ویدئو، UICollectionView با layout سفارشی. SwiftUI View — برای رابطهای استاندارد iOS 13+. ترکیب از طریق UIHostingController مجاز است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید