我使用核心数据与云工具包,因此要检查iCloud用户状态在应用程序启动。如果出现问题,我想向用户发出一个对话框,我使用UIApplication.shared.keyWindow?. rootviewcontroller ?.present(…)到目前为止。

在Xcode 11 beta 4中,现在有一个新的弃用消息,告诉我:

'keyWindow'在iOS 13.0中已弃用:不应该用于支持多个场景的应用程序,因为它在所有连接的场景中返回一个键窗口

我应该如何呈现对话呢?


当前回答

Objective C解决方案:

UIWindow *foundWindow = nil;
NSSet *scenes=[[UIApplication sharedApplication] connectedScenes];
NSArray *windows;
for(id aScene in scenes){  // it's an NSSet so you can't use the first object
    windows=[aScene windows];
    if([aScene activationState]==UISceneActivationStateForegroundActive)
         break;
}
for (UIWindow  *window in windows) {
    if (window.isKeyWindow) {
        foundWindow = window;
        break;
    }
}
 // and to find the parent viewController:
UIViewController* parentController = foundWindow.rootViewController;
while( parentController.presentedViewController &&
      parentController != parentController.presentedViewController ){
    parentController = parentController.presentedViewController;
}

其他回答

理想情况下,由于它已经被弃用,我建议你将窗口存储在SceneDelegate中。但是,如果您确实想要一个临时的解决方案,您可以创建一个过滤器并像这样检索keyWindow。

let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

下面是一个向后兼容的检测keyWindow的方法:

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

用法:

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

由于许多开发人员要求将Objective C代码的这种弃用进行替换。您可以使用下面的代码来使用keyWindow。

+(UIWindow*)keyWindow {
    UIWindow        *windowRoot = nil;
    NSArray         *windows = [[UIApplication sharedApplication]windows];
    for (UIWindow   *window in windows) {
        if (window.isKeyWindow) {
            windowRoot = window;
            break;
        }
    }
    return windowRoot;
}

我在AppDelegate类中创建并添加了这个方法作为类方法,并以下面的非常简单的方式使用它。

[AppDelegate keyWindow];

不要忘记像下面这样在AppDelegate.h类中添加这个方法。

+(UIWindow*)keyWindow;

我为一个视图分配了一个新窗口,并设置它[newWindow makeKeyAndVisible]; 当完成使用时,设置它[newWindow resignKeyWindow]; 然后尝试通过[UIApplication sharedApplication]. keywindow直接显示原始的键-窗口。

在iOS 12上一切正常,但在iOS 13上原始的键窗口不能正常显示。它显示整个白色屏幕。

我通过以下方法解决了这个问题:

UIWindow *mainWindow = nil;
if ( @available(iOS 13.0, *) ) {
   mainWindow = [UIApplication sharedApplication].windows.firstObject;
   [mainWindow makeKeyWindow];
} else {
    mainWindow = [UIApplication sharedApplication].keyWindow;
}

如果你使用SwiftLint的'first_where'规则,并想静音交战:

UIApplication.shared.windows.first(where: { $0.isKeyWindow })