ProgrammazioneSviluppatore iOS

Descrivi il ciclo di vita di un view controller in UIKit e come una gestione errata del ciclo di vita possa portare a perdite di memoria o bug nell'interfaccia utente. Quali sono le sottigliezze da conoscere?

Supera i colloqui con l'assistente IA Hintsage

Risposta

Il ciclo di vita di un UIViewController include metodi chiave:

  • init(nibName:bundle:) / init(coder:): inizializzazione
  • loadView: creazione della gerarchia delle view
  • viewDidLoad: la view è caricata (il posto ideale per la configurazione iniziale)
  • viewWillAppear / viewDidAppear: la view sta per essere mostrata / è stata mostrata
  • viewWillDisappear / viewDidDisappear: la view sta per scomparire / è scomparsa
  • deinit: rimozione del controller

L'ordine di chiamata dei metodi:

  • Prima viene creata la gerarchia delle view (loadView, poi viewDidLoad)
  • Ad ogni apparizione e scomparsa sullo schermo vengono chiamati viewWillAppear / viewWillDisappear, poi viewDidAppear / viewDidDisappear
  • Dopo la rimozione — deinit

Sottigliezze:

  • In viewDidLoad non è consigliabile accedere alle dimensioni delle view — potrebbero non essere aggiornate
  • È importante liberare le risorse (osservatori, timer) in deinit o viewWillDisappear
  • Aggiungere subview — in viewDidLoad, ma non in viewWillAppear — altrimenti potrebbe verificarsi una duplicazione ad ogni apparizione

Esempio:

class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupViews() setupBindings() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Iscriviti alle notifiche } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Disiscriversi dalle notifiche } deinit { // Pulizia } }

Domanda trabocchetto

Domanda:

È consentito al view controller accedere alle proprietà della view al di fuori del ciclo di vita (ad esempio, nel costruttore)?

Risposta: No, prima della chiamata (o sovrascrittura) di loadView, tutte le proprietà legate alla view potrebbero non essere state inizializzate. Qualsiasi accesso a esse al di fuori di loadView / viewDidLoad porterà a un crash.

Esempio:

// Errore: self.view non è ancora stata inizializzata! init() { super.init(nibName: nil, bundle: nil) self.view.backgroundColor = .red //CRASH }

Esempi di errori reali dovuti alla mancanza di conoscenza delle sottigliezze dell'argomento


Storia

Il progetto è andato in crash a causa di un accesso prematuro a self.view in init — la view non era stata creata, portando a un crash.


Storia

Nei grandi progetti si dimenticava di disiscriversi da NotificationCenter o delegate in viewWillDisappear e/o deinit, il che portava a perdite di memoria (NotificationCenter continuava a riferirsi al view controller, che non veniva liberato e continuava a ricevere eventi).


Storia

In viewWillAppear, ad ogni apparizione venivano aggiunti nuovi subview alla view (ad esempio, mostrava un indicatore di caricamento), senza controllare l'esistenza. Di conseguenza, ad ogni ritorno sullo schermo apparivano sempre più indicatori duplicati, causando malfunzionamenti nell'interfaccia utente.