«keyWindow» está obsoleto. ¿Qué hacer?
\n\nSi alguna vez has escrito:
\n\nguard let window = UIApplication.shared.keyWindow else { return }\n\n…seguramente has visto la advertencia amarilla de Xcode: «'keyWindow' was deprecated in iOS 13.0». Esta es una de las preguntas más frecuentes en Stack Overflow (más de 100,000 visitas), y con razón: Apple realmente cambió las reglas del juego.
\n\nEn este artículo analizaremos por qué sucedió esto y compararemos 4 enfoques para obtener la ventana de la aplicación sin usar la API obsoleta. Aprenderás qué método es adecuado para UIKit, SwiftUI, SceneDelegate y cuándo usar cada uno. ¡Allá vamos!
\n\n¿Por qué Apple eliminó keyWindow?
\n\nAntes de iOS 13, la aplicación tenía una ventana principal — keyWindow. Todo era simple: la tomábamos y trabajábamos. Pero con la llegada de iPadOS y la multitarea (Split View, Slide Over), una aplicación puede tener varias ventanas simultáneamente. Cada ventana es gestionada por su propio UIWindowScene. El concepto de «ventana clave» se volvió difuso.
Apple ahora recomienda obtener la ventana a través de la escena (UIWindowScene) a la que pertenece tu controlador o vista.
\n\nComparación de enfoques: de lo simple a lo correcto
\n\nVeremos 4 formas, desde «silenciar rápidamente la advertencia» hasta «hacerlo como Apple». Elige la que se adapte a tu arquitectura.
\n\n1. Solución rápida: UIApplication.shared.windows.first(where:)
\n\nLa respuesta más popular en Stack Overflow es usar la propiedad windows en lugar de keyWindow:
if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {\n // usamos window\n}\n\nVentajas:
\n- \n
- Mínimos cambios en el código \n
- Funciona en iOS 13+ \n
Desventajas:
\n- \n
- Todavía no es seguro con múltiples ventanas \n
- Puede devolver nil si la ventana aún no se ha creado \n
- Apple aún lo marca como «obsoleto» en algunos contextos \n
Cuándo usarlo: Solo para prototipos rápidos o si tienes exactamente una ventana (por ejemplo, una aplicación de iPhone sin múltiples ventanas).
\n\n2. A través de SceneDelegate: el camino correcto para UIKit
\n\nA partir de iOS 13, Apple introdujo UISceneDelegate. En el método scene(_:willConnectTo:options:) recibes un UIWindowScene y puedes guardar una referencia a la ventana.
Paso 1: En SceneDelegate.swift declara la propiedad window:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {\n\n var window: UIWindow?\n\n func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {\n guard let windowScene = (scene as? UIWindowScene) else { return }\n window = UIWindow(windowScene: windowScene)\n window?.rootViewController = ViewController()\n window?.makeKeyAndVisible()\n }\n}\n\nPaso 2: Obtén la ventana a través de la escena:
\n\nif let windowScene = view.window?.windowScene,\n let window = windowScene.windows.first {\n // usamos window\n}\n\nO, si necesitas la ventana principal en cualquier lugar de la aplicación, guarda una referencia al SceneDelegate y su window.
Ventajas:
\n- \n
- Totalmente conforme con las recomendaciones de Apple \n
- Funciona correctamente con múltiples ventanas \n
- Seguro para la multitarea en iPad \n
Desventajas:
\n- \n
- Requiere configurar SceneDelegate (si aún no lo has hecho) \n
- Un poco más de código \n
3. A través de UIWindowScene.activeWindow (iOS 15+)
\n\nA partir de iOS 15, Python. Hacia la cima del dominio. Programación concisa y eficiente Refactorización de código C++: Guía práctica para mejorar la arquitectura y la legibilidad Arquitectura de aplicaciones Swift (iOS/macOS). Patrones y prácticas Concurrencia en Rust: desde los fundamentos hasta sistemas de alta cargaUIWindowScene
Blogs
Book Recommendations
Leer también
Algoritmos y estructuras de datos en PHP: guía completa para desarrolladores
Docker y PHP: Contenerización de aplicaciones — Guía completa
Import cycle not allowed en Go: cómo romper el círculo vicioso
Cómo conseguir trabajo como desarrollador PHP: consejos y currículum en la práctica
Colas de tareas en TypeScript: guía práctica