«keyWindow» está obsoleto. O que fazer?
\n\nSe você já escreveu:
\n\nguard let window = UIApplication.shared.keyWindow else { return }\n\n…provavelmente viu o aviso amarelo do Xcode: «'keyWindow' was deprecated in iOS 13.0». Esta é uma das perguntas mais frequentes no Stack Overflow (mais de 100.000 visualizações), e não é à toa — a Apple realmente mudou as regras do jogo.
\n\nNeste artigo, vamos analisar por que isso aconteceu e comparar 4 abordagens para obter a janela do aplicativo sem a API obsoleta. Você aprenderá qual método é adequado para UIKit, SwiftUI, SceneDelegate e quando usar cada um deles. Vamos lá!
\n\nPor que a Apple abandonou o keyWindow?
\n\nAntes do iOS 13, o aplicativo tinha uma janela principal — keyWindow. Tudo era simples: pegávamos ela e trabalhávamos. Mas com a chegada do iPadOS e multitarefa (Split View, Slide Over), um aplicativo pode ter várias janelas simultaneamente. Cada janela é gerenciada pela sua própria UIWindowScene. O conceito de "janela chave" tornou-se confuso.
A Apple agora recomenda obter a janela através da cena (UIWindowScene) à qual seu controlador ou view pertence.
\n\nComparação das abordagens: do simples ao correto
\n\nVamos analisar 4 maneiras, desde "calar rapidamente o aviso" até "fazer do jeito Apple". Escolha a que se adequa à sua arquitetura.
\n\n1. Correção rápida: UIApplication.shared.windows.first(where:)
\n\nA resposta mais popular no Stack Overflow é usar a propriedade windows em vez de keyWindow:
if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {\n // usamos a window\n}\n\nVantagens:
\n- \n
- Mínimas alterações no código \n
- Funciona no iOS 13+ \n
Desvantagens:
\n- \n
- Ainda não é seguro com várias janelas \n
- Pode retornar nil se a janela ainda não foi criada \n
- A Apple ainda marca isso como "obsoleto" em alguns contextos \n
Quando usar: Apenas para protótipos rápidos ou se você tem certeza de que há apenas uma janela (ex.: aplicativo iPhone sem multi-janelas).
\n\n2. Através do SceneDelegate: o caminho correto para UIKit
\n\nA partir do iOS 13, a Apple introduziu o UISceneDelegate. No método scene(_:willConnectTo:options:) você recebe uma UIWindowScene e pode armazenar uma referência à janela.
Passo 1: Em SceneDelegate.swift, declare a propriedade 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\nPasso 2: Obtenha a janela através da cena:
\n\nif let windowScene = view.window?.windowScene,\n let window = windowScene.windows.first {\n // usamos a window\n}\n\nOu, se você precisar da janela principal em qualquer lugar do aplicativo, armazene uma referência ao SceneDelegate e sua window.
Vantagens:
\n- \n
- Totalmente de acordo com as recomendações da Apple \n
- Funciona corretamente com várias janelas \n
- Seguro para multitarefa no iPad \n
Desvantagens:
\n- \n
- Requer configuração do SceneDelegate (se você ainda não migrou) \n
- Um pouco mais de código \n
3. Através do UIWindowScene.activeWindow (iOS 15+)
\n\nA partir do iOS 15, o UIWindowScene
Blogs
Book Recommendations
Leia também
Iteração sobre palavras de uma string em C++: 5 maneiras do iniciante ao profissional
Web Scraping com BeautifulSoup: Guia Completo para Iniciantes
CI/CD para projetos Swift: GitHub Actions nível avançado
Por que é tão difícil colocar a primeira letra de uma string em maiúscula no Rust?
Injeção de Dependência em C++: guia completo para iniciantes