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

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

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

我应该如何呈现对话呢?


当前回答

如果你的应用还没有更新到采用基于场景的应用生命周期,另一种获得活动窗口对象的简单方法是通过UIApplicationDelegate:

let window = UIApplication.shared.delegate?.window
let rootViewController = window??.rootViewController

其他回答

由于许多开发人员要求将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;

我的解决方案如下,适用于iOS 15

let window = (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first

对于Objective-C解决方案也是如此

@implementation UIWindow (iOS13)

+ (UIWindow*) keyWindow {
   NSPredicate *isKeyWindow = [NSPredicate predicateWithFormat:@"isKeyWindow == YES"];
   return [[[UIApplication sharedApplication] windows] filteredArrayUsingPredicate:isKeyWindow].firstObject;
}

@end

如果你的应用还没有更新到采用基于场景的应用生命周期,另一种获得活动窗口对象的简单方法是通过UIApplicationDelegate:

let window = UIApplication.shared.delegate?.window
let rootViewController = window??.rootViewController

您可能知道,由于可能存在多个场景,因此不建议使用键窗口。最方便的解决方案是提供一个currentWindow作为扩展,然后进行搜索和替换。

extension UIApplication {
    var currentWindow: UIWindow? {
        connectedScenes
            .compactMap { $0 as? UIWindowScene }
            .flatMap { $0.windows }
            .first { $0.isKeyWindow }
    }
}