viewDidLoad — اولین متدی است که UIKit پس از بارگذاری View کنترلر UIViewController در حافظه فراخوانی میکند. بر اساس Apple Developer Documentation، این متد دقیقاً یک بار در طول عمر کنترلر فراخوانی میشود. viewDidLoad مکان اصلی برای تنظیم اولیه رابط کاربری، ثبت سلولها و مقداردهی اولیه دادهها است.
نکات کلیدی
viewDidLoad — یک متد نمونه از UIViewController است که UIKit بلافاصله پس از بارگذاری View کنترلر در حافظه RAM فراخوانی میکند. در این لحظه، تمام ویژگیهای IBOutlet قبلاً به عناصر رابط کاربری متصل شدهاند، اما View هنوز به سلسلهمراتب پنجرهها اضافه نشده و برای کاربر قابل مشاهده نیست. توسعهدهنده این متد را بازنویسی میکند تا پیکربندی اولیه صفحه را انجام دهد.
این متد بخشی از ViewController Lifecycle است و بلافاصله پس از loadView (اگر View به صورت برنامهنویسی ایجاد شود) یا پس از بارگذاری از Storyboard قرار میگیرد. در یک پروژه معمولی، viewDidLoad پرکاربردترین متد بازنویسیشده UIViewController است، زیرا نقطهای امن برای کار با subviews فراهم میکند که از قبل وجود دارند و آماده پیکربندی هستند.
نکته مهم: در زمان فراخوانی viewDidLoad، ابعاد View هنوز با ابعاد نهایی مطابقت ندارند — Auto Layout مراحل خود را کامل نکرده و frame ممکن است با مقدار مورد انتظار متفاوت باشد. برای محاسبات وابسته به ابعاد از viewDidLayoutSubviews استفاده میشود.
زمان فراخوانی viewDidLoad بستگی به نحوه مقداردهی کنترلر دارد. در بیشتر موارد، UIKit این متد را به طور خودکار در اولین دسترسی به ویژگی view کنترلر فراخوانی میکند — این مکانیزم lazy-loading UIViewController نامیده میشود.
وقتی NavigationController یا TabBarController برای اولین بار صفحه شما را نشان میدهد، UIKit بررسی میکند که آیا View بارگذاری شده است یا خیر. اگر نشده باشد — loadView (یا بارگذاری از Storyboard) فراخوانی میشود و بلافاصله پس از آن viewDidLoad اجرا میشود. این سناریوی استاندارد است و برای هر نمونه از کنترلر یک بار اتفاق میافتد.
override func viewDidLoad() {
super.viewDidLoad()
print("View بارگذاری شد — میتوان رابط را تنظیم کرد")
setupUI()
configureTableView()
}
viewDidLoad دوباره فراخوانی نمیشود هنگام بازگشت به صفحه از طریق back button یا dismiss. اگر منطق شما به ظاهر مجدد صفحه وابسته است — آن را در viewWillAppear قرار دهید. این یکی از رایجترین اشتباهات مفهومی است: توسعهدهندگان انتظار دارند viewDidLoad در هر نمایش فراخوانی شود، اما UIKit آن را فقط یک بار فراخوانی میکند.
گاهی توسعهدهندگان به اجبار view کنترلر را فراخوانی میکنند تا بارگذاری را از پیش آغاز کنند: let _ = controller.view. این کار باعث میشود loadView و viewDidLoad قبل از ظاهر شدن کنترلر روی صفحه فراخوانی شوند. از این ترفند زمانی استفاده میشود که نیاز به آمادهسازی View از قبل برای انتقال روان باشد.
viewDidLoad برای عملیات پیکربندی یکبارهای طراحی شده است که به قابل مشاهده بودن صفحه وابسته نیستند. استفاده صحیح از این متد کلید معماری تمیز و رفتار قابل پیشبینی کنترلر است.
در viewDidLoad فایلهای nib و کلاسها برای UITableView و UICollectionView ثبت میشوند، delegateها تنظیم میشوند و مقادیر اولیه ویژگیهای عناصر UI تعیین میشوند. از آنجایی که تمام IBOutletها در این لحظه متصل شدهاند، میتوان با خیال راحت به label.text، imageView.image و سایر ویژگیهای subviews دسترسی داشت.
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.register(
CustomCell.self,
forCellReuseIdentifier: CustomCell.identifier
)
title = "صفحه اصلی"
}
در اینجا viewModel ایجاد میشود، data source با آرایهها مقداردهی میشود و اعلانهایی که باید در طول عمر کنترلر فعال باشند مشترک میشوند. به عنوان مثال، اشتراک UIApplication.willEnterForegroundNotification برای بهروزرسانی دادهها هنگام بازگشت از پسزمینه — گزینه مناسبی برای viewDidLoad است. ViewModel در معماری مدرن iOS نقش پل ارتباطی بین کنترلر و منطق تجاری را ایفا میکند و مقداردهی آن دقیقاً در viewDidLoad تضمین میکند که دادهها در لحظه اولین نمایش صفحه آماده باشند.
به تنظیم data source برای جداول و مجموعهها توجه ویژهای داشته باشید. اگر جدول شما از UIFetchedResultsController یا NSFetchedResultsController با Core Data استفاده میکند، fetch request و delegate را در viewDidLoad مقداردهی کنید. این تضمین میکند که در اولین نمایش صفحه، جدول بدون درخواستهای اضافی با داده پر شده باشد.
در viewDidLoad دکمههای NavigationBar پیکربندی میشوند، large title تنظیم میشود، search controller اضافه میشود و دکمههای edit/done تنظیم میشوند. این عناصر به ندرت در نمایشهای مجدد صفحه تغییر میکنند، بنابراین مقداردهی آنها در اینجا بهینه است.
همه عملیاتها برای viewDidLoad مناسب نیستند. برخی اقدامات قرار داده شده در این متد منجر به مصرف بیش از حد حافظه، رفتار نادرست یا باگ در نمایشهای مجدد صفحه میشوند.
از اجرای درخواستهای شبکهای که نتیجه آنها فقط روی UI تأثیر میگذارد خودداری کنید. اگر درخواست قبل از ظاهر شدن صفحه کامل شود، کاربر نتیجه را نخواهد دید و اگر بعد از آن — دادهها ممکن است قدیمی باشند. بارگذاری را در viewDidLoad آغاز کنید، اما UI را در viewWillAppear بهروزرسانی کنید.
عملیات وابسته به ابعاد و موقعیت View را در viewDidLoad انجام ندهید. در زمان فراخوانی، Auto Layout مراحل خود را کامل نکرده و frame ممکن است نهایی نباشد. برای محاسبات از viewDidLayoutSubviews استفاده کنید یا updateViewConstraints را بازنویسی کنید.
اعلانهایی که فقط زمانی که صفحه قابل مشاهده است فعال هستند را مشترک نشوید. اعلانهای صفحه کلید، اعلانهای تغییر محتوای کنترلرهای فرزند — آنها را در viewWillAppear مشترک شوید و در viewDidDisappear لغو اشتراک کنید تا از فراخوانیهای اضافی و نشت حافظه جلوگیری شود.
متدهایی که به صفحه قابل مشاهده نیاز دارند را فراخوانی نکنید. برای مثال، تلاش برای نمایش UIAlertController از viewDidLoad باعث خطا میشود، زیرا View کنترلر هنوز به سلسلهمراتب پنجرهها اضافه نشده است. تمام عملیات UI وابسته به window یا presentedViewController فقط باید پس از ظاهر شدن صفحه انجام شوند.
منابع سنگین را بدون نیاز مقداردهی نکنید. اگر صفحه به ندرت باز میشود یا دادهها بلافاصله نمایش داده نمیشوند، ایجاد اشیاء پرمنبع را تا زمانی که واقعاً مورد نیاز هستند به تأخیر بیندازید. مقداردهی تنبل (lazy) ویژگیها در 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 در حافظه فراخوانی میکند. اگر کنترلر نابود شده و دوباره ایجاد شود، viewDidLoad برای نمونه جدید اجرا خواهد شد.
بله، حتماً. فراخوانی super.viewDidLoad تضمین میکند که UIKit تنظیمات داخلی لازم برای عملکرد صحیح Lifecycle را انجام دهد. همیشه super را به عنوان اولین اقدام در متد فراخوانی کنید.
viewDidLoad یک بار هنگام بارگذاری View فراخوانی میشود. viewWillAppear هر بار قبل از ظاهر شدن صفحه فراخوانی میشود. اولی — برای تنظیمات یکباره، دومی — برای بهروزرسانی دادهها و وضعیت.
عملیات سنگین همزمان در viewDidLoad thread اصلی را مسدود کرده و ظاهر شدن صفحه را به تأخیر میاندازد. بارگذاریهای ناهمزمان مجاز هستند، اما هنگام بهروزرسانی UI پس از اتمام آنها باید در نظر داشت که صفحه ممکن است قبلاً پنهان شده باشد.
نمیتوان مستقیماً viewDidLoad را فراخوانی کرد — UIKit آن را فراخوانی میکند. برای اجبار بارگذاری View، به ویژگی controller.view دسترسی پیدا کنید. این کار loadView و viewDidLoad را به طور خودکار اجرا میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید