How to fix deprecated keyWindow in iOS 13: complete guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

«keyWindow» is deprecated. What to do?

\n\n

If you've ever written:

\n\n
guard let window = UIApplication.shared.keyWindow else { return }
\n\n

…then you've probably seen the yellow Xcode warning: «'keyWindow' was deprecated in iOS 13.0». This is one of the most common questions on Stack Overflow (over 100,000 views), and for good reason — Apple really changed the rules of the game.

\n\n

In this article, we'll break down why this happened and compare 4 approaches to get the app window without deprecated API. You'll learn which method is suitable for UIKit, SwiftUI, SceneDelegate, and when to use each one. Let's go!

\n\n

Why did Apple deprecate keyWindow?

\n\n

Before iOS 13, an app had one main window — keyWindow. Everything was simple: grab it and use it. But with the arrival of iPadOS and multitasking (Split View, Slide Over), an app can have multiple windows simultaneously. Each window is managed by its own UIWindowScene. The concept of a «key window» became blurred.

\n\n

Apple now recommends getting the window through the scene (UIWindowScene) to which your controller or view belongs.

\n\n

Comparison of approaches: from simple to correct

\n\n

We'll look at 4 methods, from «quickly silence the warning» to «doing it the Apple way». Choose the one that fits your architecture.

\n\n

1. Quick fix: UIApplication.shared.windows.first(where:)

\n\n

The most popular answer on Stack Overflow is to use the windows property instead of keyWindow:

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

Pros:

\n
    \n
  • Minimal code changes
  • \n
  • Works on iOS 13+
  • \n
\n\n

Cons:

\n
    \n
  • Still unsafe with multiple windows
  • \n
  • May return nil if the window hasn't been created yet
  • \n
  • Apple still marks this as «deprecated» in some contexts
  • \n
\n\n

When to use: Only for a quick prototype or if you definitely have one window (e.g., an iPhone app without multi-windowing).

\n\n

2. Via SceneDelegate: the correct way for UIKit

\n\n

Starting with iOS 13, Apple introduced UISceneDelegate. In the scene(_:willConnectTo:options:) method, you receive a UIWindowScene and can save a reference to the window.

\n\n

Step 1: In SceneDelegate.swift, declare the window property:

\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

Step 2: Get the window through the scene:

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

Or, if you need the main window anywhere in the app, store a reference to the SceneDelegate and its window.

\n\n

Pros:

\n
    \n
  • Fully complies with Apple's recommendations
  • \n
  • Works correctly with multiple windows
  • \n
  • Safe for multitasking on iPad
  • \n
\n\n

Cons:

\n
    \n
  • Requires setting up SceneDelegate (if you haven't migrated yet)
  • \n
  • Slightly more code
  • \n
\n\n

3. Via UIWindowScene.activeWindow (iOS 15+)

\n\n

Starting with iOS 15, UIWindowScene

Blogs

Book Recommendations