viewDidDisappear est une méthode du cycle de vie d’UIViewController qui est appelée immédiatement après la disparition complète de la vue de l’écran de l’appareil iOS. Les développeurs l’utilisent pour arrêter les animations, libérer de la RAM, se désabonner des notifications et sauvegarder l’état actuel. Selon Apple Developer Documentation (2025), une implémentation correcte de cette méthode prévient jusqu’à 40% des fuites mémoire dans les applications avec navigation active. Sans elle, les processus en arrière-plan peuvent continuer à s’exécuter, consommant des ressources de batterie et de CPU. L’utilisation correcte de viewDidDisappear est l’une des compétences clés d’un développeur iOS, affectant directement les performances et la stabilité de l’application.
Points essentiels
viewDidDisappear est une méthode hook de la superclasse UIViewController que le système appelle après que la vue a été complètement retirée de la hiérarchie des fenêtres à l’écran. Elle fait partie du cycle de vie standard de la vue dans UIKit et fournit au développeur un point pour effectuer des opérations de finalisation.
La méthode est déclarée dans le protocole UIViewController et est disponible pour être redéfinie dans toutes les sous-classes. La signature de la méthode est : override func viewDidDisappear(_ animated: Bool). Le paramètre animated indique si la transition était accompagnée d’animation. Cela permet de distinguer les transitions programmatiques des transitions animées pour un contrôle plus précis du comportement.
Contrairement à viewWillDisappear, qui est appelée avant le début de l’animation, viewDidDisappear garantit que la vue n’est plus visible pour l’utilisateur. Ceci est critique pour les opérations qui ne doivent être exécutées qu’après que l’interface est complètement masquée — par exemple, masquer des éléments de superposition en plein écran ou terminer l’enregistrement vidéo.
La méthode est définie dans la classe de base UIViewController et a la signature suivante :
import UIKit
class MyViewController: UIViewController {
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// Libérer les ressources et se désabonner
}
}
L’appel obligatoire à super.viewDidDisappear(animated) dans la première ligne de l’implémentation est une exigence d’UIKit. Sans lui, la superclasse ne peut pas terminer correctement les processus internes liés à l’affichage de la vue. Ignorer cette règle conduit à un comportement de navigation imprévisible et à des plantages potentiels.
Le cycle de vie complet d’UIViewController se compose de six méthodes clés, chacune responsable d’une phase spécifique de l’existence de la vue. viewDidDisappear termine la séquence de disparition, en suivant viewWillDisappear. Il est important de comprendre l’ordre d’appel de toutes les méthodes pour répartir correctement l’initialisation et la libération des ressources.
La séquence lors de l’apparition de la vue : viewDidLoad → viewWillAppear → viewDidAppear. Lors du masquage : viewWillDisappear → viewDidDisappear. La phase finale — deinit, qui est appelée lorsque l’objet UIViewController est détruit. Ces six méthodes forment un cycle complet garantissant une gestion d’état prévisible.
| Méthode | Moment d’appel | Utilisation typique |
|---|---|---|
| viewDidLoad | Après le chargement de la vue en mémoire | Configuration initiale de l’interface, abonnement aux données |
| viewWillAppear | Avant l’apparition de la vue à l’écran | Mise à jour des données avant affichage |
| viewDidAppear | Après l’apparition de la vue à l’écran | Démarrage des animations, début d’observation |
| viewWillDisappear | Avant la disparition de la vue | Sauvegarde des données saisies, annulation des opérations |
| viewDidDisappear | Après la disparition de la vue | Libération des ressources, désabonnement des notifications |
| deinit | Lorsque l’objet est détruit | Nettoyage final, libération des références fortes |
Chacune de ces méthodes est appelée exactement une fois par transition correspondante. Une exception est viewDidLoad, qui peut être appelé à nouveau si le ViewController a été déchargé de la mémoire par manque de ressources puis restauré. Dans ce cas, viewDidDisappear précède le viewDidLoad répété.
Le paramètre animated dans la signature de la méthode indique si la transition était animée. Ceci est utile pour distinguer les transitions programmatiques sans animation (par exemple, lors de la définition de rootViewController) des transitions animées initiées par l’utilisateur. Si la valeur est false, le contrôleur a peut-être été masqué de force par le système — dans ce cas, certaines opérations dépendantes du temps peuvent ne pas être pertinentes.
Le système appelle viewDidDisappear dans exactement deux scénarios : lorsqu’un ViewController est supprimé de la pile de navigation et lorsqu’il est recouvert par un autre contrôleur. Dans les deux cas, la méthode signale que la vue n’est plus visible pour l’utilisateur et le développeur doit libérer les ressources qui ne sont pas nécessaires en arrière-plan. Comprendre ces scénarios évite les hypothèses erronées sur l’état de l’application.
Le premier scénario — pop depuis UINavigationController. Lorsque l’utilisateur appuie sur le bouton de retour, popViewController:animated est appelé. Le contrôleur actuel reçoit viewDidDisappear, puis, s’il n’y a plus de références fortes vers lui, deinit. Le deuxième scénario — present/dismiss. Lorsqu’un nouveau contrôleur est présenté modalement, le presentingViewController reçoit viewDidDisappear. Lors du dismiss, cette méthode est appelée sur le contrôleur qui a été présenté modalement.
Le troisième scénario, moins évident — ajout d’un child ViewController. Si un nouveau contrôleur enfant est ajouté à un contrôleur conteneur (par exemple, UIPageViewController ou UITabBarController), le contrôleur enfant actif reçoit viewDidDisappear. Ceci est crucial pour les applications avec des onglets ou des carrousels de pages — chaque changement d’onglet doit suspendre correctement le travail de l’écran inactif.
Il existe une exception importante : si un UIViewController est affiché dans une fenêtre modale et que l’utilisateur le ferme de manière interactive en balayant vers le bas, le système peut ne pas appeler viewDidDisappear si le geste n’est pas terminé. Ce comportement est apparu dans iOS 13 avec le dismiss interactif. Les développeurs doivent gérer l’état via UIAdaptivePresentationControllerDelegate et la méthode didDismiss pour garantir la réception de l’événement.
Une autre particularité — avertissements de mémoire. Lorsque la mémoire est faible, le système peut décharger la vue d’un contrôleur qui n’est pas visible à l’écran. Dans ce cas, viewDidDisappear est généralement appelée avant le déchargement, mais le développeur doit dupliquer les opérations de nettoyage critiques dans didReceiveMemoryWarning comme filet de sécurité. Cette approche évite la perte de données dans des scénarios extrêmes.
viewDidDisappear est utilisée pour trois catégories principales d’opérations : arrêt des activités, libération des ressources et sauvegarde de l’état. Chaque catégorie a ses propres bonnes pratiques développées par la communauté des développeurs iOS. Examinons les scénarios les plus courants avec des exemples d’implémentation.
Une erreur typique est de s’abonner aux notifications dans viewDidLoad et de ne jamais se désabonner. Cela provoque l’appel du gestionnaire sur un objet désalloué, entraînant un plantage. L’approche correcte consiste à s’abonner dans viewWillAppear et à se désabonner dans viewDidDisappear, ce qui garantit que l’abonnement n’est actif que lorsque le contrôleur est affiché à l’écran.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleKeyboardShow),
name: UIResponder.keyboardWillShowNotification,
object: nil
)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
Ce motif garantit que le gestionnaire de notifications n’est actif que lorsque le contrôleur est visible à l’écran. Lors de la navigation vers un autre écran, tous les abonnements sont automatiquement supprimés et restaurés au retour. Cela augmente la fiabilité de l’application et élimine une classe de bogues liés aux notifications.
Examinons deux exemples pratiques d’utilisation de viewDidDisappear dans des projets réels. Le premier exemple montre l’arrêt d’un minuteur lors du masquage de l’écran, le second montre la fin correcte de l’observation du clavier. Les deux exemples suivent le principe de libération des ressources lorsque le contrôleur est inactif.
Si un Timer s’exécute à l’écran pour mettre à jour l’interface (par exemple, un compte à rebours ou un carrousel), il doit être arrêté lorsque le contrôleur est masqué. Continuer le minuteur en arrière-plan consomme non seulement des ressources CPU, mais peut aussi provoquer une exception en tentant de mettre à jour une interface invisible.
class CountdownViewController: UIViewController {
private var countdownTimer: Timer?
private var remainingSeconds: Int = 60
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startTimer()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
invalidateTimer()
}
private func invalidateTimer() {
countdownTimer()?.invalidate()
countdownTimer = nil
}
}
Dans de nombreuses applications, un AVPlayer lit une vidéo dans un lecteur intégré. Si l’utilisateur navigue vers un autre écran, la vidéo doit être automatiquement mise en pause. Implémenter cela dans viewDidDisappear garantit que la pause a lieu après que l’écran est complètement masqué — cela évite le scintillement d’une image noire pendant la transition.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if player().timeControlStatus == .playing {
player().pause()
playerLayer().removeFromSuperlayer()
}
player = nil
}
La mise à zéro de la variable player après la pause libère supplémentairement la mémoire occupée par les tampons vidéo. Cette approche est particulièrement importante pour les applications avec de longues vidéos, où le tampon peut occuper des dizaines de mégaoctets. Combiner la pause avec la mise à zéro des références minimise l’empreinte de l’application en arrière-plan.
viewDidDisappear est souvent confondue avec viewWillDisappear et deinit, mais chacune de ces méthodes a son propre domaine de responsabilité. Comprendre les limites entre elles est la clé d’une architecture d’application iOS stable. Une utilisation incorrecte peut entraîner une double libération de ressources ou, au contraire, des fuites de ressources.
La principale différence entre viewDidDisappear et viewWillDisappear est le moment de l’appel. viewWillDisappear est appelée lorsque la vue est encore visible mais se prépare à disparaître. Cela convient pour sauvegarder les données visibles (texte dans les champs de saisie). viewDidDisappear est appelée après la fin de l’animation, lorsque la vue n’est plus visible — idéale pour libérer les ressources non liées à l’état visuel.
deinit, contrairement à viewDidDisappear, n’est appelé que lorsque l’objet UIViewController est détruit en mémoire. Si le contrôleur est simplement masqué (par exemple, recouvert par une fenêtre modale), deinit n’est pas appelé. Dans cette situation, viewDidDisappear est le seul point pour effectuer des opérations de finalisation. Le nettoyage complet des ressources doit se faire dans deinit, mais viewDidDisappear gère la libération temporaire jusqu’à la prochaine apparition.
Lors du développement avec SwiftUI, la méthode viewDidDisappear n’est pas utilisée — elle est remplacée par le modificateur .onDisappear qui fonctionne de manière similaire. Cependant, SwiftUI manque de contrôle direct du cycle de vie, et les développeurs comptent sur Combine et les objets State pour la gestion des ressources. Pour les applications UIKit, viewDidDisappear reste l’outil principal pour gérer la disparition de l’écran.
Même les développeurs iOS expérimentés commettent des erreurs en travaillant avec viewDidDisappear. Examinons les cinq problèmes les plus courants et les moyens de les prévenir. Connaître ces anti-patrons aidera à éviter des bogues difficiles à trouver liés au cycle de vie du contrôleur.
Une attention particulière doit être accordée à la sécurité des threads. Si viewDidDisappear est appelée sur le thread principal (ce qui est garanti par UIKit), mais que le nettoyage des ressources implique des opérations asynchrones, l’accès aux données partagées doit être synchronisé. Utiliser DispatchQueue.main.async dans viewDidDisappear pour mettre à jour l’interface après l’achèvement d’une tâche asynchrone est une approche courante mais correcte.
Un autre anti-patron important — appel de méthodes déléguées dans viewDidDisappear qui peuvent initier une nouvelle transition ou une présentation modale. Cela crée un cycle où viewDidDisappear peut être appelée à nouveau avant la fin du premier appel. Apple recommande d’éviter les présentations modales dans les méthodes du cycle de vie, en les déplaçant vers des gestionnaires d’événements séparés.
Questions fréquentes
viewWillDisappear est appelée avant le début de l’animation de masquage, lorsque la vue est encore visible. viewDidDisappear est appelée après la disparition complète de la vue. Utilisez viewWillDisappear pour sauvegarder les données et viewDidDisappear pour libérer les ressources.
Oui, l’appel à super.viewDidDisappear(animated) est obligatoire. UIKit utilise cette méthode pour les notifications internes et la finalisation de l’état de transition. Sans l’appel à super, UINavigationController et UITabBarController peuvent mal fonctionner.
Oui, avec le dismiss interactif dans iOS 13+ (balayage vers le bas), la méthode peut ne pas être appelée si le geste n’est pas terminé. Pour garantir la réception de l’événement, utilisez le délégué UIAdaptivePresentationControllerDelegate et la méthode presentationControllerDidDismiss.
deinit n’est appelé que lors de la destruction de l’objet, tandis que viewDidDisappear est appelée à chaque masquage. Pour libérer des ressources à chaque transition (par exemple, se désabonner des notifications), utilisez viewDidDisappear. Pour le nettoyage final lors de la suppression du contrôleur, utilisez deinit.
Dans SwiftUI, au lieu de viewDidDisappear, le modificateur .onDisappear { } est utilisé. Il est appelé lorsque la vue disparaît de la hiérarchie. Contrairement à UIKit, SwiftUI ne garantit pas que onDisappear sera appelé dans tous les scénarios d’animation.
Résumé
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.
Lisez aussi