我使用核心数据与云工具包,因此要检查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中已弃用:不应该用于支持多个场景的应用程序,因为它在所有连接的场景中返回一个键窗口
我应该如何呈现对话呢?
当前回答
通常使用
斯威夫特5
UIApplication.shared.windows.filter {$0.isKeyWindow}.first
另外,在UIViewController中:
self.view.window
视图。窗口是当前场景的窗口
WWDC 2019:
关键的窗口 手动跟踪窗口
在iPad上介绍多个Windows - WWDC 2019 -视频-苹果开发人员 支持iPad上的多个Windows |苹果开发者文档
其他回答
灵感来自berni的回答
let keyWindow = Array(UIApplication.shared.connectedScenes)
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first(where: { $0.isKeyWindow })
试试这个:
UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController!.present(alert, animated: true, completion: nil)
iOS 16,兼容至iOS 15
由于这个帖子在三年后仍有流量,我想分享我认为目前功能最优雅的解决方案。它也适用于SwiftUI。
UIApplication
.shared
.connectedScenes
.compactMap { ($0 as? UIWindowScene)?.keyWindow }
.first
iOS 15和16,兼容至iOS 13
UIApplication
.shared
.connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }
注意,connectedScenes只在iOS 13之后才可用。如果你需要支持早期版本的iOS,你必须把这个放在If #available(iOS 13, *)语句中。
变体:更长,但更容易理解的变体:
UIApplication
.shared
.connectedScenes
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first { $0.isKeyWindow }
iOS 13和14
下面的历史答案在iOS 15上仍然有效,但应该被替换,因为UIApplication.shared.windows已弃用。感谢@matt指出这一点!
最初的回答:
在matt的精彩回答基础上稍作改进,这个回答更简单、更简短、更优雅:
UIApplication.shared.windows.first { $0.isKeyWindow }
这是我的解决方案:
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.compactMap({$0 as? UIWindowScene})
.first?.windows
.filter({$0.isKeyWindow}).first
使用如:
keyWindow?.endEditing(true)
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
}
}