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

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

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

我应该如何呈现对话呢?


当前回答

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

@implementation UIWindow (iOS13)

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

@end

其他回答

一个UIApplication扩展:

extension UIApplication {

    /// The app's key window taking into consideration apps that support multiple scenes.
    var keyWindowInConnectedScenes: UIWindow? {
        return windows.first(where: { $0.isKeyWindow })
    }

}

用法:

let myKeyWindow: UIWindow? = UIApplication.shared.keyWindowInConnectedScenes

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

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

我在这里提出的建议在iOS 15中已弃用。现在怎么办?好吧,如果一个应用没有自己的多个窗口,我假设接受的现代方式将是获得应用的第一个connectedscene,强制到一个UIWindowScene,并获得它的第一个窗口。但这几乎正是公认的答案所做的!所以我的变通办法在这一点上感觉相当无力。但是,由于历史原因,我还是让它保持原样。


公认的答案虽然巧妙,但可能过于详尽。你可以更简单地得到完全相同的结果:

UIApplication.shared.windows.filter {$0.isKeyWindow}.first

我还要提醒大家,不要过于认真地对待keyWindow的弃用。完整的警告信息如下:

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

所以如果你不支持iPad上的多窗口,继续使用keyWindow是没有异议的。

试试这个:

UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController!.present(alert, animated: true, completion: nil)

Berni的代码很好,但它不工作时,应用程序从后台回来。

这是我的代码:

class var safeArea : UIEdgeInsets
{
    if #available(iOS 13, *) {
        var keyWindow = UIApplication.shared.connectedScenes
                .filter({$0.activationState == .foregroundActive})
                .map({$0 as? UIWindowScene})
                .compactMap({$0})
                .first?.windows
                .filter({$0.isKeyWindow}).first
        // <FIX> the above code doesn't work if the app comes back from background!
        if (keyWindow == nil) {
            keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow }
        }
        return keyWindow?.safeAreaInsets ?? UIEdgeInsets()
    }
    else {
        guard let keyWindow = UIApplication.shared.keyWindow else { return UIEdgeInsets() }
        return keyWindow.safeAreaInsets
    }
}