viewDidDisappear: esencia del método, ciclo de vida de UIViewController y cuándo se llama

Autor: IT Sectr Publicado: 2026-03-05 Tiempo de lectura: 9 min

viewDidDisappear es un método del ciclo de vida de UIViewController que se llama inmediatamente después de que la vista desaparece por completo de la pantalla del dispositivo iOS. Los desarrolladores lo utilizan para detener animaciones, liberar memoria RAM, cancelar suscripciones a notificaciones y guardar el estado actual. Según Apple Developer Documentation (2025), la implementación correcta de este método previene hasta un 40% de fugas de memoria en aplicaciones con navegación activa. Sin él, los procesos en segundo plano pueden continuar ejecutándose, consumiendo recursos de batería y CPU. El uso correcto de viewDidDisappear es una de las habilidades clave de un desarrollador iOS, que afecta directamente al rendimiento y la estabilidad de la aplicación.

Puntos clave

  • viewDidDisappear — el método final del ciclo de vida que se llama después de que la vista desaparece de la pantalla
  • Se utiliza para liberar recursos: detener temporizadores, ocultar indicadores de carga
  • Necesario para cancelar la suscripción de NotificationCenter y observaciones KVO para evitar fugas
  • Se diferencia de viewWillDisappear en que se llama después de que finaliza la animación de transición
  • No reemplaza a deinit — deinit se encarga de la destrucción final del objeto

¿Qué es viewDidDisappear?

viewDidDisappear es un método hook de la superclase UIViewController que el sistema llama después de que la vista se elimina por completo de la jerarquía de ventanas en la pantalla. Forma parte del ciclo de vida estándar de la vista en UIKit y proporciona al desarrollador un punto para realizar operaciones de finalización.

El método se declara en el protocolo UIViewController y está disponible para sobrescribirse en todas las subclases. La firma del método es: override func viewDidDisappear(_ animated: Bool). El parámetro animated indica si la transición fue acompañada de animación. Esto permite distinguir entre transiciones programáticas y animadas para un control de comportamiento más preciso.

A diferencia de viewWillDisappear, que se llama antes de que comience la animación, viewDidDisappear garantiza que la vista ya no es visible para el usuario. Esto es crítico para operaciones que solo deben ejecutarse después de que la interfaz esté completamente oculta — por ejemplo, ocultar elementos superpuestos en pantalla completa o finalizar la grabación de video.

Firma y declaración

El método se define en la clase base UIViewController y tiene la siguiente firma:

swift
import UIKit

class MyViewController: UIViewController {
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Liberar recursos y cancelar suscripción
    }
}

La llamada obligatoria a super.viewDidDisappear(animated) en la primera línea de la implementación es un requisito de UIKit. Sin ella, la superclase no puede completar correctamente los procesos internos relacionados con la visualización de la vista. Ignorar esta regla conduce a un comportamiento impredecible de la navegación y posibles fallos.

Lugar de viewDidDisappear en el ciclo de vida de UIViewController

El ciclo de vida completo de UIViewController consta de seis métodos clave, cada uno responsable de una fase específica de la existencia de la vista. viewDidDisappear completa la secuencia de ocultación, después de viewWillDisappear. Es importante entender el orden de llamada de todos los métodos para distribuir correctamente la inicialización y la liberación de recursos.

La secuencia cuando aparece la vista: viewDidLoadviewWillAppearviewDidAppear. Al ocultar: viewWillDisappearviewDidDisappear. La fase final — deinit, que se llama cuando se destruye el objeto UIViewController. Estos seis métodos forman un ciclo completo que garantiza una gestión de estado predecible.

MétodoMomento de llamadaUso típico
viewDidLoadDespués de cargar la vista en memoriaConfiguración inicial de la interfaz, suscripción a datos
viewWillAppearAntes de que la vista aparezca en pantallaActualizar datos antes de mostrar
viewDidAppearDespués de que la vista aparece en pantallaIniciar animaciones, comenzar observación
viewWillDisappearAntes de que la vista desaparezcaGuardar datos ingresados, cancelar operaciones
viewDidDisappearDespués de que la vista desapareceLiberar recursos, cancelar suscripción a notificaciones
deinitCuando se destruye el objetoLimpieza final, liberar referencias fuertes

Cada uno de estos métodos se llama exactamente una vez por transición correspondiente. Una excepción es viewDidLoad, que puede llamarse de nuevo si el ViewController se descargó de la memoria por falta de recursos y luego se restauró. En tal caso, viewDidDisappear precederá al viewDidLoad repetido.

Relación con la animación de transición

El parámetro animated en la firma del método indica si la transición fue animada. Esto es útil para distinguir entre transiciones programáticas sin animación (por ejemplo, al establecer un rootViewController) y transiciones animadas iniciadas por el usuario. Si el valor es false, es posible que el controlador haya sido ocultado por el sistema de forma forzada — en este caso, algunas operaciones dependientes del tiempo pueden no ser relevantes.

Cuándo se llama a viewDidDisappear

El sistema llama a viewDidDisappear exactamente en dos escenarios: cuando un ViewController se elimina de la pila de navegación y cuando es cubierto por otro controlador. En ambos casos, el método señala que la vista ya no es visible para el usuario, y el desarrollador debe liberar los recursos que no son necesarios en segundo plano. Comprender estos escenarios previene suposiciones incorrectas sobre el estado de la aplicación.

El primer escenario — pop de UINavigationController. Cuando el usuario presiona el botón de retroceso, se llama a popViewController:animated. El controlador actual recibe viewDidDisappear y luego, si no hay más referencias fuertes a él, deinit. El segundo escenario — present/dismiss. Cuando se presenta un nuevo controlador de forma modal, el presentingViewController recibe viewDidDisappear. Al hacer dismiss, este método se llama en el controlador que se presentó modalmente.

El tercer escenario, menos obvio — agregar un child ViewController. Si se agrega un nuevo controlador hijo a un controlador contenedor (por ejemplo, UIPageViewController o UITabBarController), el controlador hijo activo recibe viewDidDisappear. Esto es crítico para aplicaciones con pestañas o carruseles de páginas — cada cambio de pestaña debe suspender correctamente el trabajo de la pantalla inactiva.

Excepciones y casos no obvios

Existe una excepción importante: si un UIViewController se muestra en una ventana modal y el usuario lo cierra de forma interactiva deslizando hacia abajo, el sistema puede no llamar a viewDidDisappear si el deslizamiento no se completa. Este comportamiento apareció en iOS 13 junto con el dismiss interactivo. Los desarrolladores deben manejar el estado a través de UIAdaptivePresentationControllerDelegate y el método didDismiss para garantizar la recepción del evento.

Otra característica — memory warnings. Cuando la memoria es escasa, el sistema puede descargar la vista de un controlador que no es visible en pantalla. En este caso, viewDidDisappear generalmente se llama antes de la descarga, pero el desarrollador debe duplicar las operaciones de limpieza críticamente importantes en didReceiveMemoryWarning como medida de seguridad. Este enfoque evita la pérdida de datos en escenarios extremos.

Casos de uso típicos

viewDidDisappear se utiliza para tres categorías principales de operaciones: detener actividades, liberar recursos y guardar estado. Cada categoría tiene sus propias mejores prácticas desarrolladas por la comunidad de desarrolladores iOS. Veamos los escenarios más comunes con ejemplos de implementación.

  • Detener animaciones — llamar a layer.removeAllAnimations() para CALayer, detener bloques UIView.animate
  • Liberar recursos — anular imágenes grandes, limpiar datos en caché, cerrar descriptores de archivos
  • Cancelar suscripción a notificaciones — eliminar observadores de NotificationCenter.default, detener observaciones KVO
  • Guardar progreso — escribir borradores en CoreData o UserDefaults al cerrar la pantalla de edición
  • Ocultar superposiciones — eliminar indicadores de carga, tooltips y elementos popover que no deben permanecer después de una transición

Ejemplo: cancelar suscripción de NotificationCenter

Un error típico es suscribirse a notificaciones en viewDidLoad y nunca cancelar la suscripción. Esto provoca que el manejador se llame en un objeto desasignado, causando un crash. El enfoque correcto es suscribirse en viewWillAppear y cancelar la suscripción en viewDidDisappear, lo que garantiza que la suscripción esté activa solo mientras el controlador se muestra en pantalla.

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

Este patrón garantiza que el manejador de notificaciones solo esté activo cuando el controlador es visible en pantalla. Al navegar a otra pantalla, todas las suscripciones se eliminan automáticamente y se restauran al regresar. Esto aumenta la confiabilidad de la aplicación y elimina una clase de errores relacionados con las notificaciones.

Ejemplos de código en Swift

Examinemos dos ejemplos prácticos del uso de viewDidDisappear en proyectos reales. El primer ejemplo demuestra la detención de un temporizador cuando se oculta la pantalla, el segundo muestra la finalización correcta de la observación del teclado. Ambos ejemplos siguen el principio de liberar recursos cuando el controlador está inactivo.

Detener un temporizador

Si se ejecuta un Timer en pantalla para actualizar la interfaz (por ejemplo, una cuenta regresiva o un carrusel), debe detenerse cuando se oculta el controlador. Continuar el temporizador en segundo plano no solo consume recursos de CPU, sino que también puede causar una excepción al intentar actualizar una interfaz invisible.

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

Pausar video al ocultar

En muchas aplicaciones, un AVPlayer reproduce video en un reproductor integrado. Si el usuario navega a otra pantalla, el video debe pausarse automáticamente. Implementar esto en viewDidDisappear garantiza que la pausa ocurra después de que la pantalla esté completamente oculta — esto evita el parpadeo de un fotograma negro durante la transición.

swift
override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    if player().timeControlStatus == .playing {
        player().pause()
        playerLayer().removeFromSuperlayer()
    }
    player = nil
}

Anular la variable player después de pausar libera adicionalmente la memoria ocupada por los búferes de video. Este enfoque es especialmente importante para aplicaciones con videos largos, donde el búfer puede ocupar decenas de megabytes. Combinar la pausa con la anulación de referencias minimiza el footprint de la aplicación en segundo plano.

viewDidDisappear y otros métodos del ciclo de vida

viewDidDisappear a menudo se confunde con viewWillDisappear y deinit, pero cada uno de estos métodos tiene su propia área de responsabilidad. Comprender los límites entre ellos es clave para una arquitectura de aplicación iOS estable. Un uso incorrecto puede provocar una doble liberación de recursos o, por el contrario, fugas de recursos.

La principal diferencia entre viewDidDisappear y viewWillDisappear es el momento de la llamada. viewWillDisappear se llama cuando la vista aún es visible pero se prepara para desaparecer. Esto es adecuado para guardar datos visibles (texto en campos de entrada). viewDidDisappear se llama después de que la animación se completa, cuando la vista ya no es visible — ideal para liberar recursos no relacionados con el estado visual.

deinit, a diferencia de viewDidDisappear, se llama solo cuando el objeto UIViewController se destruye en memoria. Si el controlador simplemente está oculto (por ejemplo, cubierto por una ventana modal), deinit no se llama. En esta situación, viewDidDisappear es el único punto para realizar operaciones de finalización. La limpieza completa de recursos debe ocurrir en deinit, pero viewDidDisappear maneja la liberación temporal hasta la próxima aparición.

Cuándo usar cada método

  • viewWillDisappear — guardar datos ingresados, enviar análisis sobre el inicio de la transición
  • viewDidDisappear — detener animaciones, cancelar suscripción a notificaciones, ocultar elementos superpuestos
  • deinit — liberación final de grandes recursos, cerrar conexiones de red

Al desarrollar con SwiftUI, el método viewDidDisappear no se utiliza — es reemplazado por el modificador .onDisappear, que funciona de manera similar. Sin embargo, SwiftUI carece de control directo sobre el ciclo de vida, y los desarrolladores dependen de Combine y objetos State para la gestión de recursos. Para aplicaciones UIKit, viewDidDisappear sigue siendo la herramienta principal para gestionar la desaparición de la pantalla.

Errores comunes en la implementación

Incluso los desarrolladores iOS experimentados cometen errores al trabajar con viewDidDisappear. Examinemos los cinco problemas más comunes y las formas de prevenirlos. Conocer estos anti-patrones ayudará a evitar errores difíciles de encontrar relacionados con el ciclo de vida del controlador.

  • Falta de super.viewDidDisappear — llamar a super es obligatorio para el correcto funcionamiento de UIKit; su ausencia puede causar la interrupción del estado interno del controlador
  • Operaciones pesadas en viewDidDisappear — la escritura síncrona de grandes datos en viewDidDisappear bloquea el hilo principal y degrada la animación de transición
  • Suscripción olvidada a notificaciones — si no se llama a removeObserver en viewDidDisappear, el manejador puede activarse en un objeto zombie, causando EXC_BAD_ACCESS
  • Doble cancelación de suscripción — eliminar un observador que ya fue eliminado en otro lugar provoca NSInternalInconsistencyException
  • Dependencia del orden de llamada — en contenedores anidados, el orden de llamada de viewDidDisappear para los controladores hijo y padre no está garantizado

Se debe prestar especial atención a la seguridad de hilos. Si viewDidDisappear se llama en el hilo principal (lo que está garantizado por UIKit), pero la limpieza de recursos implica operaciones asíncronas, se debe sincronizar el acceso a los datos compartidos. Usar DispatchQueue.main.async dentro de viewDidDisappear para actualizar la interfaz después de completar una tarea asíncrona es un enfoque común pero correcto.

Otro anti-patrón importante — llamar a métodos delegados dentro de viewDidDisappear que puedan iniciar una nueva transición o presentación modal. Esto crea un ciclo donde viewDidDisappear puede ser llamado nuevamente antes de que la primera llamada se complete. Apple recomienda evitar presentaciones modales dentro de los métodos del ciclo de vita, trasladándolas a manejadores de eventos separados.

Preguntas frecuentes

¿En qué se diferencia viewDidDisappear de viewWillDisappear?

viewWillDisappear se llama antes de que comience la animación de ocultación, cuando la vista aún es visible. viewDidDisappear se llama después de que la vista ha desaparecido por completo. Use viewWillDisappear para guardar datos y viewDidDisappear para liberar recursos.

¿Es necesario llamar a super.viewDidDisappear?

Sí, llamar a super.viewDidDisappear(animated) es obligatorio. UIKit utiliza este método para notificaciones internas y completar el estado de la transición. Sin la llamada a super, UINavigationController y UITabBarController pueden funcionar mal.

¿Puede viewDidDisappear no ser llamado?

Sí, con dismiss interactivo en iOS 13+ (deslizar hacia abajo), el método puede no ser llamado si el gesto no se completa. Para garantizar la recepción del evento, use el delegado UIAdaptivePresentationControllerDelegate y el método presentationControllerDidDismiss.

¿Qué es mejor: viewDidDisappear o deinit?

deinit se llama solo cuando se destruye el objeto, mientras que viewDidDisappear se llama en cada ocultación. Para liberar recursos en cada transición (por ejemplo, cancelar suscripción a notificaciones), use viewDidDisappear. Para la limpieza final cuando se elimina el controlador, use deinit.

¿Cómo funciona viewDidDisappear en SwiftUI?

En SwiftUI, en lugar de viewDidDisappear, se utiliza el modificador .onDisappear { }. Se llama cuando la vista desaparece de la jerarquía. A diferencia de UIKit, SwiftUI no garantiza que onDisappear se llame en todos los escenarios de animación.

Resumen

  • viewDidDisappear — el último método del ciclo de vida antes de ocultar, se llama después de que la animación de transición se completa
  • Propósito principal — liberar recursos, detener temporizadores y cancelar suscripción a notificaciones
  • Es obligatorio llamar a super.viewDidDisappear para el correcto funcionamiento de UIKit
  • Se diferencia de viewWillDisappear en el momento de la llamada: después de la animación, no antes
  • No reemplaza a deinit — deinit se llama cuando se destruye el objeto, viewDidDisappear en cada ocultación
  • No se utiliza para operaciones síncronas pesadas — bloquean el hilo principal y alteran la animación
  • En iOS 13+ se requiere manejo adicional a través de UIAdaptivePresentationControllerDelegate para una llamada garantizada

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