Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve: 'keyWindow' was deprecated in iOS 13.0

Edit The suggestion I make here is deprecated in iOS 15. So now what? Well, if an app doesn't have multiple windows of its own, I presume the accepted modern way would be to get the first of the app's connectedScenes, coerce to a UIWindowScene, and take its first window. But that is almost exactly what the accepted answer does! So my workaround feels rather feeble at this point. However, I'll let it stand for historical reasons.


The accepted answer, while ingenious, might be overly elaborate. You can get exactly the same result much more simply:

UIApplication.shared.windows.filter {$0.isKeyWindow}.first

I would also caution that the deprecation of keyWindow should not be taken overly seriously. The full warning message reads:

'keyWindow' was deprecated in iOS 13.0: Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes

So if you are not supporting multiple windows on iPad there is no objection to going ahead and continuing to use keyWindow.


This is my solution:

let keyWindow = UIApplication.shared.connectedScenes
        .filter({$0.activationState == .foregroundActive})
        .compactMap({$0 as? UIWindowScene})
        .first?.windows
        .filter({$0.isKeyWindow}).first

Usage e.g.:

keyWindow?.endEditing(true)

iOS 15, compatible down to iOS 13

UIApplication
.shared
.connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }

Note that connectedScenes is available only since iOS 13. If you need to support earlier versions of iOS, you have to place this in an if #available(iOS 13, *) statement.

A variant that is longer, but easier to understand:

UIApplication
.shared
.connectedScenes
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first { $0.isKeyWindow }

iOS 13 and 14

The following historical answer is still valid on iOS 15, but should be replaced because UIApplication.shared.windows is deprecated. Thanks to @matt for pointing this out!

Original answer:

Improving slightly on matt's excellent answer, this is even simpler, shorter, and more elegant:

UIApplication.shared.windows.first { $0.isKeyWindow }

Here is a backward-compatible way of detecting keyWindow:

extension UIWindow {
    static var key: UIWindow? {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
        } else {
            return UIApplication.shared.keyWindow
        }
    }
}

Usage:

if let keyWindow = UIWindow.key {
    // Do something
}

Usually use

Swift 5

UIApplication.shared.windows.filter {$0.isKeyWindow}.first

In addition,in the UIViewController:

self.view.window

view.window is current window for scenes

WWDC 2019: enter image description here

Key Windows

  • Track windows manually
  • Introducing Multiple Windows on iPad - WWDC 2019 - Videos - Apple Developer
  • Supporting Multiple Windows on iPad | Apple Developer Documentation