Como corrigir o keyWindow obsoleto no iOS 13: guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

«keyWindow» está obsoleto. O que fazer?

\n\n

Se você já escreveu:

\n\n
guard 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\n

Neste 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\n

Por que a Apple abandonou o keyWindow?

\n\n

Antes 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.

\n\n

A Apple agora recomenda obter a janela através da cena (UIWindowScene) à qual seu controlador ou view pertence.

\n\n

Comparação das abordagens: do simples ao correto

\n\n

Vamos analisar 4 maneiras, desde "calar rapidamente o aviso" até "fazer do jeito Apple". Escolha a que se adequa à sua arquitetura.

\n\n

1. Correção rápida: UIApplication.shared.windows.first(where:)

\n\n

A resposta mais popular no Stack Overflow é usar a propriedade windows em vez de keyWindow:

\n\n
if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {\n    // usamos a window\n}
\n\n

Vantagens:

\n
    \n
  • Mínimas alterações no código
  • \n
  • Funciona no iOS 13+
  • \n
\n\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
\n\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\n

2. Através do SceneDelegate: o caminho correto para UIKit

\n\n

A 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.

\n\n

Passo 1: Em SceneDelegate.swift, declare a propriedade window:

\n\n
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\n

Passo 2: Obtenha a janela através da cena:

\n\n
if let windowScene = view.window?.windowScene,\n   let window = windowScene.windows.first {\n    // usamos a window\n}
\n\n

Ou, se você precisar da janela principal em qualquer lugar do aplicativo, armazene uma referência ao SceneDelegate e sua window.

\n\n

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
\n\n

Desvantagens:

\n
    \n
  • Requer configuração do SceneDelegate (se você ainda não migrou)
  • \n
  • Um pouco mais de código
  • \n
\n\n

3. Através do UIWindowScene.activeWindow (iOS 15+)

\n\n

A partir do iOS 15, o UIWindowScene

Blogs

Book Recommendations