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)
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:
Key Windows
- Track windows manually
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With