问题
I'm converting my iOS13 app for iPadOS to SceneDelegate (multi window).
How can I get the current UIWindow from the current SceneDelegate?
I know that a can access the current scene using UIView.window
or UIViewController.view.window
, but I have a non UI class (AppDelegate) where I need to get the window (keyWindow until iOS12) to show a snack bar on top of everything.
I used to do [UIApplication sharedApplication].keyWindow
but now, of course, that's wrong.
回答1:
You'll want to simply iterate through all your windows and find the key window manually.
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if (window.isKeyWindow) {
// you have the key window
break;
}
}
DO NOT use UISceneActivationStateForegroundActive
as the check. That means something different and folks are introducing bugs by using logic to find the first UISceneActivationStateForegroundActive
window scene.
回答2:
Swift 5.x / iOS 13.x
Inspired by many solutions, to get back my old window property (searching it inside the connectedScenes) I've realized a little extension:
extension UIApplication {
var currentWindow: UIWindow? {
connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
}
}
Usage:
if let window = UIApplication.shared.currentWindow {
// do whatever you want with window
}
回答3:
It sounds like you probably want to move this logic to your SceneDelegate.
The SceneDelegate now has knowledge of whether the window is connected to the scene, so it might make sense to have every connected scene listen to whatever event is driving the snack bar, and the show it on its window. This would then result in every visible window showing the snack bar (1 or more).
回答4:
You could try:
if let window = UIApplication.shared.windows.first(where: { (window) -> Bool in window.isKeyWindow}) {
//your code
}
Hope this helps!
回答5:
Now you have more than one window, one for each scene. First, you have to answer which one you need at the moment of usage.
Probably you want to get the window of the currently active scene then you can use this:
UIWindow* window = nil;
if (@available(iOS 13.0, *))
{
for (UIWindowScene* wScene in [UIApplication sharedApplication].connectedScenes)
{
if (wScene.activationState == UISceneActivationStateForegroundActive)
{
window = wScene.windows.firstObject;
break;
}
}
}
回答6:
I haven't tried this yet, but you should be able to get all the windows with [UIApplication sharedApplication].windows
and then pick if you want to show the snack bar on all of the windows or one window.
来源:https://stackoverflow.com/questions/57009283/how-get-current-keywindow-equivalent-for-multi-window-scenedelegate-xcode-11