我使用核心数据与云工具包,因此要检查iCloud用户状态在应用程序启动。如果出现问题,我想向用户发出一个对话框,我使用UIApplication.shared.keyWindow?. rootviewcontroller ?.present(…)到目前为止。
在Xcode 11 beta 4中,现在有一个新的弃用消息,告诉我:
'keyWindow'在iOS 13.0中已弃用:不应该用于支持多个场景的应用程序,因为它在所有连接的场景中返回一个键窗口
我应该如何呈现对话呢?
我使用核心数据与云工具包,因此要检查iCloud用户状态在应用程序启动。如果出现问题,我想向用户发出一个对话框,我使用UIApplication.shared.keyWindow?. rootviewcontroller ?.present(…)到目前为止。
在Xcode 11 beta 4中,现在有一个新的弃用消息,告诉我:
'keyWindow'在iOS 13.0中已弃用:不应该用于支持多个场景的应用程序,因为它在所有连接的场景中返回一个键窗口
我应该如何呈现对话呢?
当前回答
我的解决方案如下,适用于iOS 15
let window = (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first
其他回答
灵感来自berni的回答
let keyWindow = Array(UIApplication.shared.connectedScenes)
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first(where: { $0.isKeyWindow })
对于Objective-C解决方案也是如此
@implementation UIWindow (iOS13)
+ (UIWindow*) keyWindow {
NSPredicate *isKeyWindow = [NSPredicate predicateWithFormat:@"isKeyWindow == YES"];
return [[[UIApplication sharedApplication] windows] filteredArrayUsingPredicate:isKeyWindow].firstObject;
}
@end
对于Objective-C解决方案
+ (UIWindow *)keyWindow
{
NSArray<UIWindow *> *windows = [[UIApplication sharedApplication] windows];
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
return window;
}
}
return nil;
}
如果你的应用还没有更新到采用基于场景的应用生命周期,另一种获得活动窗口对象的简单方法是通过UIApplicationDelegate:
let window = UIApplication.shared.delegate?.window
let rootViewController = window??.rootViewController
- (UIWindow *)mainWindow {
NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator];
for (UIWindow *window in frontToBackWindows) {
BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen;
BOOL windowIsVisible = !window.hidden && window.alpha > 0;
BOOL windowLevelSupported = (window.windowLevel >= UIWindowLevelNormal);
BOOL windowKeyWindow = window.isKeyWindow;
if(windowOnMainScreen && windowIsVisible && windowLevelSupported && windowKeyWindow) {
return window;
}
}
return nil;
}