.onDisappear: principio de funcionamiento y uso en SwiftUI

Autor: IT Sectr Publicado: 2026-06-26 Tiempo de lectura: 10 min

.onDisappear es un modificador de SwiftUI que ejecuta un closure cuando una View se elimina de la jerarquía de la interfaz. La llamada ocurre al cerrar una pantalla, cambiar de pestaña, descartar una ventana modal o desplazar un elemento fuera de la vista. Según la Documentación para desarrolladores de Apple (2026), onDisappear no garantiza la llamada en escenarios de fallo o cuando la aplicación es terminada por el watchdog del sistema. Más información sobre SwiftUI en el artículo sobre SwiftUI.

Puntos clave

  • .onDisappear es un modificador de SwiftUI para ejecutar código cuando una View desaparece.
  • Simetría — onDisappear es complementario de onAppear y se llama en orden inverso.
  • Limpieza de recursos — caso principal: cancelar temporizadores, cerrar conexiones, guardar estado.
  • Analítica — con onDisappear se envían eventos de cierre de pantalla, tiempo de permanencia y fin de sesión.
  • Sin garantía — onDisappear no se llama cuando la aplicación falla.

¿Qué es .onDisappear?

.onDisappear es un modificador de View en SwiftUI que toma un closure Void y lo ejecuta cuando la View se elimina de la jerarquía. Junto con .onAppear, forma el ciclo de vida completo de una pantalla: aparición — trabajo — desaparición. Apple presentó onDisappear junto con SwiftUI en iOS 13 como análogo de viewDidDisappear de UIKit.

Sintácticamente, .onDisappear es idéntico a onAppear: modifica cualquier View y adjunta un closure que el renderizador de SwiftUI llama cuando la vista se elimina. A diferencia de UIKit, donde viewDidDisappear se activa solo después de completar la animación de transición, onDisappear en SwiftUI puede llamarse antes de que finalice la animación — en el momento en que la View se marca para su eliminación.

Sintaxis de onDisappear

Sintaxis básica de onDisappear es tan concisa como la de onAppear. El modificador no acepta parámetros adicionales — solo el closure, que se ejecuta sincrónicamente en el hilo principal.

swift
struct DetailView: View {
    var body: some View {
        Text("Detail Screen")
            .onDisappear {
                print("DetailView desapareció de la pantalla")
            }
    }
}

Cómo funciona .onDisappear

Mecanismo de llamada de onDisappear es opuesto al de onAppear: los elementos hijos reciben onDisappear primero, luego el padre. Esta regla child-first garantiza que los recursos hijos se liberen antes de que se liberen los recursos del padre. Si un elemento hijo depende de datos del padre, debe poder terminar correctamente sin el contexto del padre.

SwiftUI llama a onDisappear cuando la View se elimina del grafo de renderizado. Los desencadenantes incluyen: pop de NavigationStack, cambio de TabView, descarte de modal (sheet/fullScreenCover) o una View renderizada condicionalmente (if/switch). En List y ScrollView, onDisappear se llama cuando una celda se desplaza más allá del búfer de precarga.

Orden de llamada child-first

Orden child-first significa que si un VStack tiene tres View hijas, onDisappear se llama primero para cada hijo en orden inverso, luego para el padre. Esto es crítico para una limpieza adecuada: los temporizadores hijos se cancelan antes de que el ViewModel padre libere los recursos compartidos.

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

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

Salida en consola: Child B onDisappear, Child A onDisappear, Parent onDisappear — último. El orden inverso en comparación con onAppear garantiza una cadena de limpieza correcta.

Cuándo se llama a .onDisappear

Escenarios de llamada de onDisappear dependen del tipo de contenedor. En NavigationStack, onDisappear se activa al hacer pop-to-root, pop-back normal o al descartar la pantalla con deslizamiento (interactivePopGestureRecognizer). En TabView, cambiar de pestaña llama a onDisappear para la pestaña oculta y onAppear para la mostrada — ambos modificadores se activan casi simultáneamente.

En Sheet y fullScreenCover, onDisappear se llama al descartar programáticamente (mediante @Environment(\.dismiss)) o con un gesto de deslizamiento hacia abajo. Un detalle importante: si se abrió un sheet pero el usuario cambió de aplicación, onDisappear NO se llama hasta el cierre real.

EscenarioonDisappear se llamaNota
Pop en NavigationStackInmediatamente después de la animación
Cambio de pestaña TabViewPestaña actual
Descarte de sheetAntes de completar la animación
Desplazamiento en ListCelda salió de la zona de precarga
Minimizar aplicaciónNoSin garantía de llamada
Fallo/watchdog killNoNo se llama

Ejemplos de .onDisappear

Casos de uso principales de onDisappear son la limpieza de recursos, guardar estado y el seguimiento. A diferencia de onAppear, las tareas de onDisappear se ejecutan al salir y no necesitan comprobaciones de duplicación ya que la View desaparece una sola vez.

Guardar estado y cancelar temporizadores

Guardar estado en onDisappear es especialmente útil para formularios donde los datos deben guardarse al salir de la pantalla. Los temporizadores y suscripciones de Combine se cancelan en onDisappear para evitar fugas al volver a la pantalla.

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

Cancelación del temporizador en onDisappear evita la ejecución de código después de que la pantalla ya esté cerrada. Sin cancelación, el temporizador podría intentar actualizar @State que ya no pertenece a la View actual, generando una advertencia en tiempo de ejecución.

Seguimiento de tiempo en pantalla

Tiempo de permanencia en una pantalla es un escenario clásico de seguimiento. Registrar el tiempo en onAppear, calcular la diferencia en onDisappear y enviar un evento analítico con la duración de la sesión.

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 — diferencias

La diferencia clave entre onDisappear y onAppear es el orden de llamada y las garantías de ejecución. onAppear se llama cuando se añade una View a la jerarquía y puede volver a llamarse al recrearse. onDisappear se llama al eliminar y solo se garantiza que se active en un cierre normal, no en escenarios de fallo.

Según WWDC 2024, Apple recomienda tratar onDisappear como un punto de limpieza, no como un punto de confirmación de datos. Los datos críticos (pagos, registros) deben guardarse en tiempo real, no en el momento en que la View desaparece, ya que no se garantiza que onDisappear se llame al minimizar la aplicación.

Característica.onAppear.onDisappear
Momento de llamadaView añadida a la jerarquíaView eliminada de la jerarquía
OrdenParent-firstChild-first
GarantíaAltaNo en fallos
Tarea principalInicializaciónLimpieza
Llamada repetidaAl recrear la ViewUna vez por desaparición

Recomendación: use onDisappear solo para limpieza no crítica y seguimiento. Para la persistencia de datos, use scenePhase o las notificaciones applicationWillTerminate en AppDelegate.

Casos de uso típicos

Escenario 1: reproducción tipo YouTube. En la pantalla de detalles de video, onDisappear guarda la posición de reproducción en UserDefaults. Al reabrir, onAppear restaura la posición desde UserDefaults, creando una experiencia de visualización continua.

Escenario 2: cancelar suscripción de Combine. Si un ViewModel usa publicadores de Combine, onDisappear cancela la suscripción mediante cancellable?.cancel(). Esto evita actualizaciones de la UI después de salir de la pantalla, lo que es especialmente importante para listas con paginación y consultas de búsqueda.

Escenario 3: cerrar WebSocket. En aplicaciones con conexiones en tiempo real (mensajería, feeds de cotizaciones), onDisappear cierra la conexión WebSocket para ahorrar batería y datos. La reconexión ocurre en onAppear al volver a la pantalla.

Cerrar WebSocket en onDisappear

WebSocket es un recurso típico que debe cerrarse al salir de la pantalla. En el siguiente ejemplo, onDisappear desconecta el socket y onAppear lo reconecta, lo que proporciona un ahorro significativo de datos para aplicaciones con múltiples pantallas.

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

Importante: al cambiar entre pestañas de TabView, onDisappear de la pestaña actual y onAppear de la siguiente se activan casi simultáneamente. Para WebSocket esto puede causar un ciclo de desconexión-reconexión que genera carga innecesaria. La solución es usar un retardo o verificar si el socket es necesario en la siguiente pantalla.

Preguntas frecuentes

¿Puede .onDisappear no llamarse?

Sí, .onDisappear no garantiza la llamada en caso de fallo de la aplicación (crash, watchdog kill), minimización de la aplicación sin cerrar la pantalla o escenarios del sistema donde la aplicación se termina en segundo plano. Para datos críticos, use scenePhase o applicationWillTerminate.

¿Cómo distinguir .onDisappear de .scenePhase?

.onDisappear se activa cuando una View se elimina de la jerarquía — un callback local para una pantalla específica. .scenePhase (mediante @Environment(\.scenePhase)) se activa cuando cambia el estado de toda la aplicación: active, inactive, background. Use onAppear+onDisappear para el seguimiento del tiempo en pantalla y scenePhase para la persistencia del estado global.

¿Por qué .onDisappear se llama varias veces seguidas?

La causa es el cambio rápido de pestañas o el push/pop repetido de la misma pantalla. SwiftUI puede crear una nueva instancia de View, eliminar la anterior, crear de nuevo — cada vez llamando a onDisappear y onAppear. Verifique si está usando .id(), .equatable() o recreando la View en el body del padre.

¿Funciona .onDisappear en SwiftUI en macOS?

Sí, .onDisappear es totalmente compatible con macOS (10.15+) con el mismo comportamiento: se llama al cerrar la ventana, eliminar un panel de split view o descartar un modal. En macOS, onDisappear también se llama al ocultar la ventana (no solo al cerrarla), lo que es importante tener en cuenta para las aplicaciones de macOS.

¿Cómo cancelar URLSessionTask en .onDisappear?

Guarde una referencia a URLSessionTask en @State y llame a task.cancel() en onDisappear. Alternativamente, use el modificador .task, que cancela automáticamente la operación asíncrona cuando la View desaparece. .task es preferible para todas las operaciones asíncronas, incluida URLSession.

Resumen

  • .onDisappear — modificador complementario de onAppear para limpieza de recursos y seguimiento cuando una View desaparece.
  • Orden child-first — las View hijas reciben onDisappear antes que el padre para una cadena de limpieza correcta.
  • Sin garantía de llamada — en caso de fallo, minimización o terminación del sistema, onDisappear puede no activarse.
  • Casos de uso principales — cancelar temporizadores, cerrar WebSocket, guardar estado, seguimiento de tiempo.
  • Analítica — onDisappear envía eventos screen_close con el tiempo de permanencia calculado mediante Date().timeIntervalSince.
  • Para operaciones asíncronas — use .task en lugar de onDisappear con Task {}, ya que .task cancela automáticamente las solicitudes.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también