ProgrammationDéveloppeur iOS

Décrivez le cycle de vie d'un view controller dans UIKit, et comment une mauvaise gestion de ce cycle peut entraîner des fuites de mémoire ou des bugs dans l'UI. Quelles subtilités faut-il connaître ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Le cycle de vie d'un UIViewController comprend des méthodes clés :

  • init(nibName:bundle:) / init(coder:) : initialisation
  • loadView : création de la hiérarchie de views
  • viewDidLoad : la view est chargée (endroit idéal pour la configuration initiale)
  • viewWillAppear / viewDidAppear : la view va apparaître/apparue
  • viewWillDisappear / viewDidDisappear : la view va disparaître/disparue
  • deinit : suppression du contrôleur

Ordre d'appel des méthodes :

  • D'abord, la hiérarchie de views est créée (loadView, puis viewDidLoad)
  • À chaque apparition et disparition sur l'écran, viewWillAppear/viewWillDisappear sont appelés, puis viewDidAppear/viewDidDisappear
  • Après suppression — deinit

Subtilités :

  • Dans viewDidLoad, il ne faut pas accéder aux dimensions de la view — elles peuvent être non valables
  • Il est important de libérer les ressources (observateurs, minuteurs) dans deinit ou viewWillDisappear
  • Ajouter des subviews — dans viewDidLoad, mais pas dans viewWillAppear — sinon, il est possible d'avoir des doublons à chaque apparition

Exemple :

class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupViews() setupBindings() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // S'abonner aux notifications } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Se désabonner des notifications } deinit { // Nettoyage } }

Question piège

Question :

Un view controller est-il autorisé à accéder aux propriétés de la view en dehors du cycle de vie (par exemple, dans le constructeur) ?

Réponse : Non, avant l'appel (ou la redéfinition) de loadView, toutes les propriétés liées à la view peuvent être non initialisées. Tout accès à ces propriétés en dehors de loadView/viewDidLoad entraînera un crash.

Exemple :

// Erreur : self.view n'est pas encore initialisé ! init() { super.init(nibName: nil, bundle: nil) self.view.backgroundColor = .red //CRASH }

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Le projet plantait à cause d'un accès prématuré à self.view dans init — la view n'était pas créée, ce qui entraînait un crash.


Histoire

Dans de grands projets, on oubliait de se désabonner de NotificationCenter ou du delegate dans viewWillDisappear et/ou deinit, ce qui entraînait des fuites de mémoire (NotificationCenter faisait référence au view controller, celui-ci n'était pas libéré et continuait à écouter les événements).


Histoire

Dans viewWillAppear, à chaque apparition, de nouveaux subviews étaient ajoutés à la view (par exemple, on montrait un indicateur de chargement), sans vérifier leur existence. En conséquence, à chaque retour à l'écran, de plus en plus d'indicateurs de doublon apparaissaient, l'UI devenait défaillante.