viewDidLoad — este prima metodă pe care UIKit o apelează după încărcarea View a UIViewController în memorie. Conform Apple Developer Documentation, această metodă este apelată exact o dată pe întreaga durată de existență a controlerului. viewDidLoad este locul principal pentru configurarea inițială a interfeței, înregistrarea celulelor și inițializarea datelor.
Principalele puncte
viewDidLoad — este o metodă de instanță a UIViewController pe care UIKit o apelează imediat după ce View a controlerului a fost încărcată în memoria RAM. În acest moment, toate proprietățile IBOutlet sunt deja conectate la elementele interfeței, dar View nu a fost încă adăugată în ierarhia ferestrelor și nu este vizibilă pentru utilizator. Dezvoltatorul suprascrie această metodă pentru a efectua configurarea inițială a ecranului.
Metoda face parte din ViewController Lifecycle și urmează imediat după loadView, dacă View este creată programatic, sau după încărcarea din Storyboard. Într-un proiect tipic, viewDidLoad este cea mai frecvent suprascrisă metodă a UIViewController, deoarece oferă un punct sigur pentru lucrul cu subviews care există deja și sunt gata de configurare.
Un detaliu important: în momentul apelării viewDidLoad, dimensiunile View nu corespund încă celor finale — Auto Layout nu a finalizat trecerile, iar frame poate diferi de cel așteptat. Pentru calcule dependente de dimensiuni se utilizează viewDidLayoutSubviews.
Momentul apelării viewDidLoad depinde de modul în care este inițializat controlerul. În majoritatea cazurilor, UIKit apelează această metodă automat la prima accesare a proprietății view a controlerului — acesta se numește mecanismul lazy-loading al UIViewController.
Când NavigationController sau TabBarController afișează pentru prima dată ecranul dvs., UIKit verifică dacă View este încărcată. Dacă nu — se apelează loadView (sau încărcarea din Storyboard), după care imediat se declanșează viewDidLoad. Acesta este scenariul standard și are loc o singură dată pentru fiecare instanță a controlerului.
override func viewDidLoad() {
super.viewDidLoad()
print("View încărcată — se poate configura interfața")
setupUI()
configureTableView()
}
viewDidLoad nu este apelat din nou la revenirea pe ecran prin back button sau dismiss. Dacă logica dvs. depinde de faptul că ecranul apare din nou — plasați-o în viewWillAppear. Aceasta este una dintre cele mai frecvente erori conceptuale: dezvoltatorii se așteaptă ca viewDidLoad să se activeze la fiecare afișare, dar UIKit îl apelează doar o dată.
Uneori dezvoltatorii forțează apelarea view a controlerului pentru a iniția încărcarea în avans: let _ = controller.view. Aceasta forțează apelarea loadView și viewDidLoad înainte ca controlerul să apară pe ecran. Acest truc este utilizat atunci când trebuie să pregătiți View din timp pentru o tranziție fluidă.
viewDidLoad este destinat operațiilor de configurare unică care nu depind de vizibilitatea ecranului. Utilizarea corectă a acestei metode este cheia unei arhitecturi curate și a unui comportament previzibil al controlerului.
În viewDidLoad se înregistrează fișierele nib și clasele pentru UITableView și UICollectionView, se configurează delegații, se stabilesc valorile inițiale ale proprietăților elementelor UI. Deoarece toate IBOutlet-urile sunt deja conectate în acest moment, se poate accesa în siguranță label.text, imageView.image și alte proprietăți ale subviews.
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.register(
CustomCell.self,
forCellReuseIdentifier: CustomCell.identifier
)
title = "Ecran principal"
}
Aici se creează viewModel, se inițializează data source cu tablouri, se abonează notificările care trebuie să funcționeze pe tot parcursul vieții controlerului. De exemplu, abonarea la UIApplication.willEnterForegroundNotification pentru actualizarea datelor la revenirea din fundal — un candidat potrivit pentru viewDidLoad. ViewModel în arhitectura modernă iOS servește ca punte de legătură între controler și logica de business, iar inițializarea sa chiar în viewDidLoad asigură pregătirea datelor în momentul primei apariții a ecranului.
Acordați o atenție deosebită configurării data source pentru tabele și colecții. Dacă tabelul dvs. utilizează UIFetchedResultsController sau NSFetchedResultsController cu Core Data, inițializați fetch request și delegatul în viewDidLoad. Aceasta garantează că la prima apariție a ecranului, tabelul va fi deja populat cu date fără interogări suplimentare.
În viewDidLoad se configurează butoanele NavigationBar, se setează large title, se adaugă search controller și se stabilesc butoanele edit/done. Aceste elemente se schimbă rar la reafișările ecranului, deci inițializarea lor aici este optimă.
Nu toate operațiile sunt potrivite în viewDidLoad. Unele acțiuni plasate în această metodă duc la consum excesiv de memorie, comportament incorect sau erori la reafișarea ecranului.
Evitați lansarea cererilor de rețea al căror rezultat afectează doar UI. Dacă cererea se finalizează înainte de apariția ecranului, utilizatorul nu va vedea rezultatul, iar dacă după — datele pot fi învechite. Inițiați încărcarea în viewDidLoad, dar actualizați UI în viewWillAppear.
Nu efectuați în viewDidLoad operații dependente de dimensiunile și poziția View. La momentul apelării, Auto Layout nu a finalizat trecerile, iar frame poate fi nefinal. Pentru calcule utilizați viewDidLayoutSubviews sau suprascrieți updateViewConstraints.
Nu vă abonați la notificări care funcționează doar când ecranul este vizibil. Notificările de tastatură, notificările de modificare a conținutului controlerelor copil — abonați-vă la ele în viewWillAppear și dezabonați-vă în viewDidDisappear pentru a evita apelurile inutile și scurgerile de memorie.
Nu apelați metode care necesită un ecran vizibil. De exemplu, încercarea de a afișa UIAlertController din viewDidLoad va cauza o eroare, deoarece View a controlerului nu a fost încă adăugată în ierarhia ferestrelor. Orice operații UI dependente de window sau presentedViewController trebuie efectuate doar după apariția ecranului.
Nu inițializați resurse grele fără necesitate. Dacă ecranul este deschis rar sau datele nu sunt afișate imediat, amânați crearea obiectelor consumatoare de resurse până când sunt cu adevărat necesare. Inițializarea leneșă (lazy) a proprietăților în Swift este un mecanism încorporat pentru rezolvarea acestei sarcini: o proprietate cu modificatorul lazy va fi creată doar la prima accesare, ceea ce economisește memorie și accelerează încărcarea ecranului.
Nu utilizați viewDidLoad pentru operații care trebuie executate la fiecare apariție a ecranului. Aceasta este cea mai fundamentală eroare: dezvoltatorii începători plasează adesea logica de actualizare a datelor în viewDidLoad și se mira că la revenirea de pe un alt ecran tabelul nu se reîncarcă. Dacă operația trebuie să se repete la fiecare afișare — utilizați viewWillAppear. Dacă trebuie să se execute o dată în timpul vieții — viewDidLoad. Amintiți-vă această regulă simplă pentru a evita majoritatea problemelor cu ciclul de viață al UIViewController.
Să analizăm trei exemple practice care demonstrează utilizarea corectă a viewDidLoad în proiecte reale. Fiecare exemplu rezolvă o sarcină specifică de configurare a ecranului.
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 = "Salut, lume!"
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
În viewDidLoad se configurează și elementele afișate în absența datelor: stare goală, loader, placeholder. Aceste componente sunt create o dată și reutilizate la fiecare apariție a ecranului. Ascunderea sau afișarea acestor elemente este controlată în viewWillAppear în funcție de datele curente.
override func viewDidLoad() {
super.viewDidLoad()
emptyStateLabel = UILabel()
emptyStateLabel.text = "Nu există date"
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()
}
Întrebări frecvente
În condiții normale nu — UIKit apelează viewDidLoad o dată după încărcarea View în memorie. Dacă controlerul este distrus și recreat, viewDidLoad va acționa pentru noua instanță.
Da, obligatoriu. Apelarea super.viewDidLoad garantează că UIKit va efectua configurarea internă necesară pentru funcționarea corectă a Lifecycle. Apelați întotdeauna super ca primul lucru în metodă.
viewDidLoad este apelat o dată la încărcarea View. viewWillAppear este apelat de fiecare dată înainte de apariția ecranului. Primul — pentru configurare unică, al doilea — pentru actualizarea datelor și stării.
Operațiile grele sincrone în viewDidLoad blochează main thread și întârzie apariția ecranului. Încărcările asincrone sunt permise, dar la actualizarea UI după finalizarea lor trebuie să țineți cont că ecranul poate fi deja ascuns.
Direct nu se poate apela viewDidLoad — îl apelează UIKit. Pentru a forța încărcarea View, accesați proprietatea controller.view. Aceasta va declanșa loadView și viewDidLoad automat.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și