ViewController — l'essence du contrôleur d'écran en iOS et son Lifecycle

Auteur : IT Sectr Publié le : 2026-02-22 Temps de lecture : 7 min

UIViewController est la classe centrale des applications iOS, gérant l'écran et son contenu. Chaque écran d'iPhone ou d'iPad est géré par un ViewController, qui coordonne l'affichage, le cycle de vie et la navigation. Pour en savoir plus sur l'architecture UIKit, consultez la documentation officielle d'Apple.

Points Clés

  • UIViewController — la classe de base pour gérer un écran dans UIKit avec son propre cycle de vie
  • viewDidLoad — appelé une fois, point d'initialisation de l'UI et d'abonnement aux données
  • viewWillAppear — l'écran sera bientôt visible, mise à jour des données avant l'affichage
  • Lifecycle comprend cinq méthodes : viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • Massive View Controller — le principal anti-patron iOS, résolu via MVVM ou Coordinator

Qu'est-ce qu'un ViewController ?

UIViewController est une classe du framework UIKit qui gère une hiérarchie de UIView et coordonne l'affichage des données à l'écran. Chaque application iOS contient au moins un ViewController — le contrôleur racine de la fenêtre. Le contrôleur gère les rotations d'écran, les transitions entre les écrans et les événements du cycle de vie.

L'architecture MVC (Model-View-Controller) en iOS est implémentée précisément via UIViewController : le contrôleur reçoit les données du modèle et met à jour la vue. Un ViewController n'est pas un élément visuel — il gère la propriété view, qui contient une hiérarchie de sous-vues. Selon Apple (2026), UIKit contient plus de 40 sous-classes intégrées de UIViewController.

Le premier iPhone SDK (2008) incluait UIViewController avec trois méthodes de cycle de vie. En 18 ans, Apple a ajouté la prise en charge de Container View Controller, des présentations adaptatives, de UIViewControllerTransitioningDelegate pour les animations personnalisées et du mode écran partagé sur iPad. UIViewController reste un composant obligatoire pour les applications UIKit.

Le cycle de vie de UIViewController

Le cycle de vie de UIViewController est une séquence de méthodes appelées par le système lors de la création, de l'affichage et du masquage d'un écran. Comprendre le cycle de vie est crucial : un placement incorrect du code entraîne des fuites de mémoire, des requêtes réseau inutiles et un scintillement de l'interface.

MéthodeMoment d'appelObjectif
viewDidLoadUne fois, après le chargement de la vue en mémoireConfiguration initiale de l'UI, abonnement Combine
viewWillAppearAvant l'apparition de l'écranMise à jour des données, masquer/afficher la barre de navigation
viewDidAppearAprès l'apparition de l'écranLancer les animations, analyses, mise à jour de la caméra
viewWillDisappearAvant de quitter l'écranSauvegarder les brouillons, se désabonner des notifications
viewDidDisappearAprès avoir quitté l'écranArrêter les processus lourds, libérer les ressources

Ordre d'appel lors de l'apparition de l'écran

Lors du premier affichage de l'écran, la séquence est : init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. Lors de la réapparition (retour d'un autre écran) : viewWillAppear → viewDidAppear. viewDidLoad n'est appelé qu'une fois pendant la durée de vie du contrôleur.

viewDidLoad, init et configuration de l'UI

La méthode viewDidLoad est le point principal de configuration de l'interface utilisateur. Elle est appelée après le chargement de la vue en mémoire, lorsque toutes les connexions IBOutlet sont déjà établies. Ici, les éléments d'UI sont créés par programmation, les contraintes sont configurées et les données initiales sont chargées.

swift
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)
    }
}

Dans SwiftUI, ce code équivaut au corps de la View. Mais UIViewController offre un contrôle total sur le cycle de vie et l'optimisation. bindViewModel utilise Combine pour l'abonnement réactif — les données sont mises à jour automatiquement lorsque le modèle change.

viewWillAppear et mise à jour des données

viewWillAppear est appelé chaque fois avant l'apparition de l'écran, même s'il est déjà en mémoire. C'est l'endroit pour mettre à jour les données qui ont pu changer sur un autre écran : recharger une liste, mettre à jour le badge de notifications, configurer la barre de navigation pour un écran spécifique.

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Masquer la barre de navigation sur cet écran
    navigationController?.setNavigationBarHidden(true, animated: animated)

    // Mettre à jour les données lors du retour d'un autre écran
    tableView.reloadData()
    badgeLabel.text = "\(CartManager.shared.itemCount)"
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // Analytique : seulement après que l'utilisateur a vu l'écran
    AnalyticsService.shared.logScreenView("Profile")
}

La différence entre viewDidLoad et viewWillAppear est cruciale : viewDidLoad s'exécute une fois et convient à la configuration statique, viewWillAppear s'exécute chaque fois que l'écran est affiché et convient aux mises à jour dynamiques. Placer des requêtes réseau dans viewDidLoad entraînera l'affichage de données obsolètes lors du retour à l'écran.

Container View Controller : UINavigationController et UITabBarController

Container View Controller est un ViewController qui gère un ou plusieurs ViewControllers enfants. Apple fournit trois conteneurs intégrés : UINavigationController (pile d'écrans), UITabBarController (onglets) et UISplitViewController (maître-détail pour iPad).

UINavigationController organise les transitions dans une pile — push ajoute un écran, pop le supprime. UITabBarController bascule entre les sections indépendantes de l'application. UISplitViewController affiche deux contrôleurs côte à côte sur iPad et un sur iPhone. Un développeur peut créer un conteneur personnalisé via addChild.

swift
// Container View Controller personnalisé
final class ContainerViewController: UIViewController {

    private let sidebarVC = SidebarViewController()
    private let contentVC = ContentViewController()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Ajout d'un contrôleur enfant
        addChild(sidebarVC)
        view.addSubview(sidebarVC.view)
        sidebarVC.didMove(toParent: self)

        addChild(contentVC)
        view.addSubview(contentVC.view)
        contentVC.didMove(toParent: self)
    }
}

Le travail correct avec Container View Controller nécessite d'appeler addChild, d'ajouter la vue et didMove(toParent:) dans cet ordre. Lors de la suppression : willMove(toParent: nil), removeFromSuperview, removeFromParent. Violer la séquence entraîne des fuites de mémoire.

Résoudre Massive View Controller avec MVVM et Coordinator

Le problème de Massive View Controller survient lorsqu'un UIViewController contient des centaines de lignes de code avec de la logique métier, des requêtes réseau, de la navigation et du code d'UI. Apple reconnaît le problème et recommande MVVM (Model-View-ViewModel) avec Coordinator pour extraire la navigation.

MVVM déplace la logique métier du contrôleur vers une ViewModel. Le Controller lie uniquement la ViewModel à la View via Combine ou un délégué. Coordinator extrait la logique de navigation — création et transition entre les contrôleurs — dans une classe séparée. Cette approche a été adoptée dans les meilleures pratiques d'Apple depuis 2024.

swift
// Coordinator — gestion de la navigation
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 vs SwiftUI : quand choisir quoi

Le choix entre UIViewController et SwiftUI View dépend de l'année de début du projet, des exigences de personnalisation et de la version minimale d'iOS prise en charge. UIKit avec UIViewController reste la base pour les projets commencés avant 2020 et pour les applications avec une personnalisation profonde de l'interface.

SwiftUI convient aux nouveaux projets avec iOS 17+, aux interfaces standard et aux prototypes. Cependant, les transitions personnalisées, le travail avec la caméra, MapKit, les animations complexes de CALayer nécessitent UIViewController. Apple recommande de combiner les approches via UIHostingController (SwiftUI dans UIKit) et UIViewRepresentable (UIKit dans SwiftUI).

ScénarioUIKit (UIViewController)SwiftUI (View)
Animation personnaliséeContrôle total via UIViewPropertyAnimatorLimité via Animation
Travail avec caméraAVCaptureSession + UIViewPreviewVia UIViewControllerRepresentable
CollectionViewUICollectionView + UICollectionViewLayoutLazyVGrid/LazyHGrid
Adaptation iPadUISplitViewController + UITraitCollectionNavigationSplitView + sizeClass
Vitesse de développementPlus lent (disposition manuelle)Plus rapide (déclaratif)

Questions Fréquentes

En quoi UIViewController diffère-t-il de UIView ?

UIViewController est un contrôleur qui gère l'écran et son cycle de vie. UIView est une vue qui affiche du contenu. Un ViewController contient une hiérarchie de UIViews mais n'est pas lui-même un élément visuel. Un contrôleur gère plusieurs vues.

Qu'est-ce qu'un Massive View Controller ?

Massive View Controller est un anti-patron où UIViewController contient trop de logique : données, navigation, requêtes réseau, animation. La solution consiste à extraire le code dans des services séparés, des coordinateurs et une ViewModel (MVVM).

Comment transmettre des données entre ViewControllers ?

Quatre façons : via une propriété dans prepare(for:sender:) (Segue), via un délégué (Delegate), via une fermeture (Closure), via un service partagé. Pour un couplage faible, utilisez Coordinator + Delegate ou Combine.

Qu'est-ce qu'un Container View Controller ?

Container View Controller est un contrôleur qui gère des ViewControllers enfants. Exemples : UINavigationController, UITabBarController, UISplitViewController. Le contrôleur parent ajoute des enfants via addChild, bascule entre eux et gère leur disposition.

Quand utiliser UIViewController plutôt que SwiftUI View ?

UIViewController — pour les animations personnalisées complexes, le travail avec caméra, les cartes, la vidéo, UICollectionView avec disposition personnalisée. SwiftUI View — pour les interfaces standard sur iOS 13+. La combinaison via UIHostingController est acceptable.

Résumé

  • UIViewController — la classe centrale UIKit pour gérer l'écran, la hiérarchie UIView et le cycle de vie
  • Lifecycle se compose de cinq méthodes : viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • viewDidLoad — le point de configuration initiale de l'UI, appelé une fois pendant la durée de vie du contrôleur
  • viewWillAppear — appelé chaque fois avant l'affichage, adapté à la mise à jour des données et à la configuration de la barre de navigation
  • Container View Controller (UINavigationController, UITabBarController) gère la hiérarchie des contrôleurs enfants
  • Massive View Controller est résolu via MVVM (extraction de la logique dans ViewModel) et Coordinator (extraction de la navigation)
  • UIViewController et SwiftUI peuvent être combinés via UIHostingController et UIViewRepresentable pour les applications hybrides

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi