ViewController: la esencia del controlador de pantalla en iOS y su Lifecycle

Autor: IT Sectr Publicado: 2026-02-22 Tiempo de lectura: 7 min

UIViewController es la clase central de las aplicaciones iOS, que gestiona la pantalla y su contenido. Cada pantalla de iPhone o iPad es gestionada por un ViewController, que coordina la visualización, el ciclo de vida y la navegación. Obtenga más información sobre la arquitectura de UIKit en la documentación oficial de Apple.

Puntos Clave

  • UIViewController — la clase base para gestionar una pantalla en UIKit con su propio ciclo de vida
  • viewDidLoad — se llama una vez, punto de inicialización de la UI y suscripción a datos
  • viewWillAppear — la pantalla pronto será visible, actualización de datos antes de la visualización
  • Lifecycle incluye cinco métodos: viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • Massive View Controller — el principal antipatrón de iOS, resuelto mediante MVVM o Coordinator

¿Qué es un ViewController?

UIViewController es una clase del framework UIKit que gestiona una jerarquía de UIView y coordina la visualización de datos en la pantalla. Cada aplicación iOS contiene al menos un ViewController — el controlador raíz de la ventana. El controlador maneja las rotaciones de pantalla, las transiciones entre pantallas y los eventos del ciclo de vida.

La arquitectura MVC (Model-View-Controller) en iOS se implementa precisamente a través de UIViewController: el controlador recibe datos del modelo y actualiza la vista. Un ViewController no es un elemento visual — gestiona la propiedad view, que contiene una jerarquía de subvistas. Según Apple (2026), UIKit contiene más de 40 subclases incorporadas de UIViewController.

El primer iPhone SDK (2008) incluía UIViewController con tres métodos de ciclo de vida. Durante 18 años, Apple añadió soporte para Container View Controller, presentaciones adaptativas, UIViewControllerTransitioningDelegate para animaciones personalizadas y el modo de pantalla dividida en iPad. UIViewController sigue siendo un componente obligatorio para las aplicaciones UIKit.

El ciclo de vida de UIViewController

El ciclo de vida de UIViewController es una secuencia de métodos llamados por el sistema al crear, mostrar y ocultar una pantalla. Comprender el ciclo de vida es críticamente importante: la colocación incorrecta del código provoca fugas de memoria, solicitudes de red innecesarias y parpadeo de la interfaz.

MétodoMomento de llamadaPropósito
viewDidLoadUna vez, después de cargar la vista en memoriaConfiguración inicial de la UI, suscripción a Combine
viewWillAppearAntes de que aparezca la pantallaActualización de datos, ocultar/mostrar la barra de navegación
viewDidAppearDespués de que aparezca la pantallaIniciar animaciones, analítica, actualización de cámara
viewWillDisappearAntes de salir de la pantallaGuardar borradores, cancelar suscripción a notificaciones
viewDidDisappearDespués de salir de la pantallaDetener procesos pesados, liberar recursos

Orden de llamada al aparecer la pantalla

En la primera visualización de la pantalla, la secuencia es: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. En la reaparición (regreso de otra pantalla): viewWillAppear → viewDidAppear. viewDidLoad se llama solo una vez durante la vida del controlador.

viewDidLoad, init y configuración de la UI

El método viewDidLoad es el punto principal para configurar la interfaz de usuario. Se llama después de que la vista se carga en memoria, cuando todas las conexiones IBOutlet ya están establecidas. Aquí se crean elementos de UI mediante programación, se configuran las restricciones y se cargan los datos iniciales.

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

En SwiftUI, este código equivale al cuerpo de la View. Pero UIViewController ofrece control total sobre el ciclo de vida y la optimización. bindViewModel usa Combine para la suscripción reactiva — los datos se actualizan automáticamente cuando el modelo cambia.

viewWillAppear y actualización de datos

viewWillAppear se llama cada vez antes de que aparezca la pantalla, incluso si ya estaba en memoria. Este es el lugar para actualizar datos que podrían haber cambiado en otra pantalla: recargar una lista, actualizar la insignia de notificaciones, configurar la barra de navegación para una pantalla específica.

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

    // Ocultar la barra de navegación en esta pantalla
    navigationController?.setNavigationBarHidden(true, animated: animated)

    // Actualizar datos al regresar de otra pantalla
    tableView.reloadData()
    badgeLabel.text = "\(CartManager.shared.itemCount)"
}

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

    // Analítica: solo después de que el usuario haya visto la pantalla
    AnalyticsService.shared.logScreenView("Profile")
}

La diferencia entre viewDidLoad y viewWillAppear es crítica: viewDidLoad se ejecuta una vez y es adecuado para la configuración estática, viewWillAppear se ejecuta cada vez que se muestra la pantalla y es adecuado para actualizaciones dinámicas. Colocar solicitudes de red en viewDidLoad provocará que se muestren datos obsoletos al regresar a la pantalla.

Container View Controller: UINavigationController y UITabBarController

Container View Controller es un ViewController que gestiona uno o más ViewControllers hijos. Apple proporciona tres contenedores integrados: UINavigationController (pila de pantallas), UITabBarController (pestañas) y UISplitViewController (maestro-detalle para iPad).

UINavigationController organiza las transiciones en una pila — push agrega una pantalla, pop la elimina. UITabBarController cambia entre secciones independientes de la aplicación. UISplitViewController muestra dos controladores lado a lado en iPad y uno en iPhone. Un desarrollador puede crear un contenedor personalizado mediante addChild.

swift
// Container View Controller personalizado
final class ContainerViewController: UIViewController {

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

    override func viewDidLoad() {
        super.viewDidLoad()

        // Agregar un controlador hijo
        addChild(sidebarVC)
        view.addSubview(sidebarVC.view)
        sidebarVC.didMove(toParent: self)

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

El trabajo correcto con Container View Controller requiere llamar a addChild, agregar la vista y didMove(toParent:) en ese orden. Al eliminar: willMove(toParent: nil), removeFromSuperview, removeFromParent. Violar la secuencia provoca fugas de memoria.

Resolver Massive View Controller con MVVM y Coordinator

El problema de Massive View Controller ocurre cuando un UIViewController contiene cientos de líneas de código con lógica de negocio, solicitudes de red, navegación y código de UI. Apple reconoce el problema y recomienda MVVM (Model-View-ViewModel) junto con Coordinator para extraer la navegación.

MVVM traslada la lógica de negocio del controlador a una ViewModel. El Controller solo vincula la ViewModel con la View a través de Combine o un delegado. Coordinator extrae la lógica de navegación — creación y transición entre controladores — en una clase separada. Este enfoque se ha adoptado en las mejores prácticas de Apple desde 2024.

swift
// Coordinator — gestión de navegación
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: cuándo elegir cada uno

La elección entre UIViewController y SwiftUI View depende del año de inicio del proyecto, los requisitos de personalización y la versión mínima compatible de iOS. UIKit con UIViewController sigue siendo la base para proyectos iniciados antes de 2020 y para aplicaciones con personalización profunda de la interfaz.

SwiftUI es adecuado para nuevos proyectos con iOS 17+, interfaces estándar y prototipos. Sin embargo, las transiciones personalizadas, el trabajo con la cámara, MapKit, las animaciones complejas de CALayer requieren UIViewController. Apple recomienda combinar enfoques mediante UIHostingController (SwiftUI dentro de UIKit) y UIViewRepresentable (UIKit dentro de SwiftUI).

EscenarioUIKit (UIViewController)SwiftUI (View)
Animación personalizadaControl total mediante UIViewPropertyAnimatorLimitado a través de Animation
Trabajo con cámaraAVCaptureSession + UIViewPreviewA través de UIViewControllerRepresentable
CollectionViewUICollectionView + UICollectionViewLayoutLazyVGrid/LazyHGrid
Adaptación iPadUISplitViewController + UITraitCollectionNavigationSplitView + sizeClass
Velocidad de desarrolloMás lento (layout manual)Más rápido (declarativo)

Preguntas Frecuentes

¿En qué se diferencia UIViewController de UIView?

UIViewController es un controlador que gestiona la pantalla y su ciclo de vida. UIView es una vista que muestra contenido. Un ViewController contiene una jerarquía de UIViews pero no es en sí mismo un elemento visual. Un controlador gestiona múltiples vistas.

¿Qué es un Massive View Controller?

Massive View Controller es un antipatrón donde UIViewController contiene demasiada lógica: datos, navegación, solicitudes de red, animaciones. La solución consiste en extraer el código en servicios separados, coordinadores y ViewModel (MVVM).

¿Cómo pasar datos entre ViewControllers?

Cuatro formas: mediante una propiedad en prepare(for:sender:) (Segue), mediante un delegado (Delegate), mediante un cierre (Closure), mediante un servicio compartido. Para un acoplamiento débil, use Coordinator + Delegate o Combine.

¿Qué es un Container View Controller?

Container View Controller es un controlador que gestiona ViewControllers hijos. Ejemplos: UINavigationController, UITabBarController, UISplitViewController. El controlador padre añade hijos mediante addChild, cambia entre ellos y gestiona su layout.

¿Cuándo usar UIViewController en lugar de SwiftUI View?

UIViewController — para animaciones personalizadas complejas, trabajo con cámara, mapas, vídeo, UICollectionView con layout personalizado. SwiftUI View — para interfaces estándar en iOS 13+. Es aceptable combinar mediante UIHostingController.

Resumen

  • UIViewController — la clase central de UIKit para gestionar la pantalla, la jerarquía de UIView y el ciclo de vida
  • Lifecycle consta de cinco métodos: viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • viewDidLoad — el punto de configuración inicial de la UI, se llama una vez durante la vida del controlador
  • viewWillAppear — se llama cada vez antes de la visualización, adecuado para actualizar datos y configurar la barra de navegación
  • Container View Controller (UINavigationController, UITabBarController) gestiona la jerarquía de controladores hijos
  • Massive View Controller se resuelve mediante MVVM (extracción de lógica en ViewModel) y Coordinator (extracción de navegación)
  • UIViewController y SwiftUI se pueden combinar mediante UIHostingController y UIViewRepresentable para aplicaciones híbridas

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