.onDisappear : principe de fonctionnement et utilisation dans SwiftUI

Auteur : IT Sectr Publié le : 2026-06-26 Temps de lecture : 10 min

.onDisappear est un modificateur SwiftUI qui exécute une closure lorsqu'une View est supprimée de la hiérarchie de l'interface. L'appel se produit lors de la fermeture d'un écran, du changement d'onglet, du rejet d'une fenêtre modale ou du défilement d'un élément hors de la visibilité. Selon la Documentation développeur Apple (2026), onDisappear ne garantit pas l'appel dans les scénarios de plantage ou lorsque l'application est terminée par le watchdog système. Pour en savoir plus sur SwiftUI, consultez l'article sur SwiftUI.

Points clés

  • .onDisappear — modificateur SwiftUI pour exécuter du code lors de la disparition d'une View.
  • Symétrie — onDisappear est le pendant de onAppear et est appelé dans l'ordre inverse.
  • Nettoyage des ressources — scénario principal : annuler les minuteries, fermer les connexions, sauvegarder l'état.
  • Analytique — via onDisappear, on envoie les événements de fermeture d'écran, de temps de séjour et de fin de session.
  • Aucune garantie — onDisappear n'est pas appelé en cas de plantage de l'application.

Qu'est-ce que .onDisappear ?

.onDisappear est un modificateur de View dans SwiftUI qui prend une closure Void et l'exécute lorsque la View est supprimée de la hiérarchie. Avec .onAppear, il forme le cycle de vie complet d'un écran : apparition — travail — disparition. Apple a introduit onDisappear avec SwiftUI dans iOS 13 comme analogue de viewDidDisappear d'UIKit.

Syntactiquement, .onDisappear est identique à onAppear : il modifie n'importe quelle View et attache une closure que le rendu SwiftUI appelle lorsque la vue est supprimée. Contrairement à UIKit, où viewDidDisappear se déclenche seulement après la fin de l'animation de transition, onDisappear dans SwiftUI peut être appelé avant la fin de l'animation — au moment où la View est marquée pour suppression.

Syntaxe de onDisappear

Syntaxe de base de onDisappear est aussi concise que celle de onAppear. Le modificateur ne prend aucun paramètre supplémentaire — seulement la closure, qui s'exécute de manière synchrone sur le thread principal.

swift
struct DetailView: View {
    var body: some View {
        Text("Detail Screen")
            .onDisappear {
                print("DetailView a disparu de l'écran")
            }
    }
}

Comment fonctionne .onDisappear

Mécanisme d'appel de onDisappear est l'opposé de onAppear : les éléments enfants reçoivent onDisappear en premier, puis le parent. Cette règle child-first garantit que les ressources enfant sont libérées avant que les ressources parent ne soient libérées. Si un élément enfant dépend des données parent, il doit pouvoir se terminer correctement sans le contexte parent.

SwiftUI appelle onDisappear lorsque la View est supprimée du graphe de rendu. Les déclencheurs incluent : pop de NavigationStack, changement de TabView, rejet de modal (sheet/fullScreenCover) ou une View rendue conditionnellement (if/switch). Dans List et ScrollView, onDisappear est appelé lorsqu'une cellule défile au-delà du tampon de préchargement.

Ordre d'appel child-first

Ordre child-first signifie que si un VStack a trois View enfants, onDisappear est appelé d'abord pour chaque enfant dans l'ordre inverse, puis pour le parent. Ceci est critique pour un nettoyage approprié : les minuteries enfants sont annulées avant que le ViewModel parent ne libère les ressources partagées.

swift
struct ParentView: View {
    var body: some View {
        VStack {
            ChildView(id: "A")
            ChildView(id: "B")
        }
        .onDisappear {
            print("Parent onDisappear — dernier")
        }
    }
}

struct ChildView: View {
    let id: String
    var body: some View {
        Text("Child \(id)")
            .onDisappear {
                print("Child \(id) onDisappear")
            }
    }
}

Sortie console : Child B onDisappear, Child A onDisappear, Parent onDisappear — dernier. L'ordre inverse par rapport à onAppear garantit une chaîne de nettoyage correcte.

Quand .onDisappear est-il appelé

Scénarios d'appel de onDisappear dépendent du type de conteneur. Dans NavigationStack, onDisappear se déclenche lors du pop-to-root, du pop-back normal ou du rejet d'écran par balayage (interactivePopGestureRecognizer). Dans TabView, changer d'onglet appelle onDisappear pour l'onglet masqué et onAppear pour l'onglet affiché — les deux modificateurs se déclenchent presque simultanément.

Dans Sheet et fullScreenCover, onDisappear est appelé lors du rejet programmatique (via @Environment(\.dismiss)) ou d'un geste de balayage vers le bas. Un détail important : si un sheet a été ouvert mais que l'utilisateur a changé d'application, onDisappear n'est PAS appelé jusqu'à la fermeture effective.

ScénarioonDisappear appeléNote
Pop dans NavigationStackOuiImmédiatement après l'animation
Changement d'onglet TabViewOuiOnglet actuel
Rejet de sheetOuiAvant la fin de l'animation
Défilement dans ListOuiCellule sortie de la zone de préchargement
Minimisation de l'applicationNonAucune garantie d'appel
Plantage/watchdog killNonPas appelé

Exemples de .onDisappear

Cas d'utilisation principaux de onDisappear sont le nettoyage des ressources, la sauvegarde d'état et le suivi. Contrairement à onAppear, les tâches de onDisappear s'exécutent à la sortie et ne nécessitent pas de vérification de duplication car la View disparaît une seule fois.

Sauvegarde d'état et annulation de minuteur

Sauvegarde d'état dans onDisappear est particulièrement utile pour les formulaires où les données doivent être sauvegardées en quittant l'écran. Les minuteries et les abonnements Combine sont annulés dans onDisappear pour éviter les fuites lors du retour à l'écran.

swift
struct FormView: View {
    @State private var draftText = ""
    @State private var timer: Timer?
    
    var body: some View {
        TextField("Enter text", text: $draftText)
            .onAppear {
                timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
                    saveDraft()
                }
            }
            .onDisappear {
                timer?.invalidate()
                timer = nil
                saveDraft()
            }
    }
    
    private func saveDraft() {
        UserDefaults.standard.set(draftText, forKey: "draft")
    }
}

Annulation du minuteur dans onDisappear empêche l'exécution de code après que l'écran est déjà fermé. Sans annulation, le minuteur pourrait tenter de mettre à jour @State qui n'appartient plus à la View actuelle, provoquant un avertissement d'exécution.

Suivi du temps passé à l'écran

Temps de séjour sur un écran est un scénario de suivi classique. Enregistrez le temps dans onAppear, calculez la différence dans onDisappear et envoyez un événement analytique avec la durée de la session.

swift
struct TrackedView: View {
    @State private var appearTime: Date?
    
    var body: some View {
        Text("Tracked Screen")
            .onAppear {
                appearTime = Date()
                Analytics.shared.logEvent("screen_view", params: ["screen": "TrackedView"])
            }
            .onDisappear {
                if let start = appearTime {
                    let duration = Date().timeIntervalSince(start)
                    Analytics.shared.logEvent("screen_close", params: [
                        "screen": "TrackedView",
                        "duration_ms": Int(duration * 1000)
                    ])
                }
            }
    }
}

.onDisappear vs .onAppear — différences

La différence clé entre onDisappear et onAppear est l'ordre d'appel et les garanties d'exécution. onAppear est appelé lorsqu'une View est ajoutée à la hiérarchie et peut être rappelé lors de la recréation. onDisappear est appelé lors de la suppression et n'est garanti de se déclencher qu'en fermeture normale, pas dans les scénarios de plantage.

Selon la WWDC 2024, Apple recommande de traiter onDisappear comme un point de nettoyage, pas comme un point de validation de données. Les données critiques (paiements, inscriptions) doivent être sauvegardées en temps réel, pas au moment de la disparition de la View, car onDisappear n'est pas garanti lorsque l'application est minimisée.

Caractéristique.onAppear.onDisappear
Moment d'appelView ajoutée à la hiérarchieView retirée de la hiérarchie
OrdreParent-firstChild-first
GarantieÉlevéePas en cas de plantage
Tâche principaleInitialisationNettoyage
Appel répétéLors de la recréation de ViewUne fois par disparition

Recommandation : utilisez onDisappear uniquement pour le nettoyage non critique et le suivi. Pour la persistance des données, utilisez scenePhase ou les notifications applicationWillTerminate dans AppDelegate.

Scénarios d'utilisation typiques

Scénario 1 : lecture type YouTube. Sur l'écran des détails de la vidéo, onDisappear sauvegarde la position de lecture dans UserDefaults. À la réouverture, onAppear restaure la position depuis UserDefaults, créant une expérience de visionnage continue.

Scénario 2 : annuler un abonnement Combine. Si un ViewModel utilise des publishers Combine, onDisappear annule l'abonnement via cancellable?.cancel(). Cela empêche les mises à jour de l'UI après avoir quitté l'écran, ce qui est particulièrement important pour les listes avec pagination et les requêtes de recherche.

Scénario 3 : fermer WebSocket. Dans les applications avec connexions en temps réel (messageries, flux de cotations), onDisappear ferme la connexion WebSocket pour économiser la batterie et les données. La reconnexion se produit dans onAppear lors du retour à l'écran.

Fermeture WebSocket dans onDisappear

WebSocket est une ressource typique qui doit être fermée en quittant l'écran. Dans l'exemple ci-dessous, onDisappear déconnecte le socket et onAppear le reconnecte, offrant des économies de données significatives pour les applications avec plusieurs écrans.

swift
struct ChatView: View {
    @StateObject private var socket = WebSocketManager()
    
    var body: some View {
        ChatListView(messages: socket.messages)
            .onAppear {
                socket.connect()
            }
            .onDisappear {
                socket.disconnect()
            }
    }
}

Important : lors du changement d'onglets TabView, onDisappear de l'onglet actuel et onAppear de l'onglet suivant se déclenchent presque simultanément. Pour WebSocket, cela peut créer un cycle déconnexion-reconnexion qui génère une charge inutile. La solution est d'utiliser un délai ou de vérifier si le socket est nécessaire sur l'écran suivant.

Questions fréquentes

.onDisappear peut-il ne pas être appelé ?

Oui, .onDisappear ne garantit pas l'appel en cas de plantage de l'application (crash, watchdog kill), de minimisation de l'application sans fermer l'écran ou de scénarios système où l'application est terminée en arrière-plan. Pour les données critiques, utilisez scenePhase ou applicationWillTerminate.

Comment distinguer .onDisappear de .scenePhase ?

.onDisappear se déclenche lorsqu'une View est retirée de la hiérarchie — un rappel local pour un écran spécifique. .scenePhase (via @Environment(\.scenePhase)) se déclenche lorsque l'état de l'application entière change : active, inactive, background. Utilisez onAppear+onDisappear pour le suivi du temps passé à l'écran et scenePhase pour la persistance de l'état global.

Pourquoi .onDisappear est-il appelé plusieurs fois de suite ?

La cause est le changement rapide d'onglets ou le push/pop répété du même écran. SwiftUI peut créer une nouvelle instance de View, supprimer l'ancienne, en créer une nouvelle — chaque fois appelant onDisappear et onAppear. Vérifiez si vous utilisez .id(), .equatable() ou recréez la View dans le body parent.

.onDisappear fonctionne-t-il dans SwiftUI sur macOS ?

Oui, .onDisappear est entièrement pris en charge sur macOS (10.15+) avec le même comportement : appelé lors de la fermeture de la fenêtre, de la suppression d'un panneau de vue divisée ou du rejet d'un modal. Sur macOS, onDisappear est également appelé lors du masquage de la fenêtre (pas seulement lors de la fermeture), ce qui est important à considérer pour les applications macOS.

Comment annuler URLSessionTask dans .onDisappear ?

Enregistrez une référence à URLSessionTask dans @State et appelez task.cancel() dans onDisappear. Alternativement, utilisez le modificateur .task qui annule automatiquement l'opération asynchrone lorsque la View disparaît. .task est préféré pour toutes les opérations asynchrones, y compris URLSession.

Résumé

  • .onDisappear — modificateur jumeau de onAppear pour le nettoyage des ressources et le suivi lors de la disparition d'une View.
  • Ordre child-first — les View enfants reçoivent onDisappear avant le parent pour une chaîne de nettoyage correcte.
  • Aucune garantie d'appel — en cas de plantage, minimisation ou terminaison système, onDisappear peut ne pas se déclencher.
  • Cas d'utilisation principaux — annuler les minuteries, fermer WebSocket, sauvegarder l'état, suivre le temps.
  • Analytique — onDisappear envoie des événements screen_close avec le temps de séjour calculé via Date().timeIntervalSince.
  • Pour les opérations asynchrones — utilisez .task au lieu de onDisappear avec Task {}, car .task annule automatiquement les requêtes.

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