我使用核心数据与云工具包,因此要检查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中已弃用:不应该用于支持多个场景的应用程序,因为它在所有连接的场景中返回一个键窗口
我应该如何呈现对话呢?
当前回答
当.foregroundActive场景为空时,我遇到了这个问题
这是我的变通办法
public extension UIWindow {
@objc
static var main: UIWindow {
// Here we sort all the scenes in order to work around the case
// when no .foregroundActive scenes available and we need to look through
// all connectedScenes in order to find the most suitable one
let connectedScenes = UIApplication.shared.connectedScenes
.sorted { lhs, rhs in
let lhs = lhs.activationState
let rhs = rhs.activationState
switch lhs {
case .foregroundActive:
return true
case .foregroundInactive:
return rhs == .background || rhs == .unattached
case .background:
return rhs == .unattached
case .unattached:
return false
@unknown default:
return false
}
}
.compactMap { $0 as? UIWindowScene }
guard connectedScenes.isEmpty == false else {
fatalError("Connected scenes is empty")
}
let mainWindow = connectedScenes
.flatMap { $0.windows }
.first(where: \.isKeyWindow)
guard let window = mainWindow else {
fatalError("Couldn't get main window")
}
return window
}
}
其他回答
如果你的应用还没有更新到采用基于场景的应用生命周期,另一种获得活动窗口对象的简单方法是通过UIApplicationDelegate:
let window = UIApplication.shared.delegate?.window
let rootViewController = window??.rootViewController
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;
}
当.foregroundActive场景为空时,我遇到了这个问题
这是我的变通办法
public extension UIWindow {
@objc
static var main: UIWindow {
// Here we sort all the scenes in order to work around the case
// when no .foregroundActive scenes available and we need to look through
// all connectedScenes in order to find the most suitable one
let connectedScenes = UIApplication.shared.connectedScenes
.sorted { lhs, rhs in
let lhs = lhs.activationState
let rhs = rhs.activationState
switch lhs {
case .foregroundActive:
return true
case .foregroundInactive:
return rhs == .background || rhs == .unattached
case .background:
return rhs == .unattached
case .unattached:
return false
@unknown default:
return false
}
}
.compactMap { $0 as? UIWindowScene }
guard connectedScenes.isEmpty == false else {
fatalError("Connected scenes is empty")
}
let mainWindow = connectedScenes
.flatMap { $0.windows }
.first(where: \.isKeyWindow)
guard let window = mainWindow else {
fatalError("Couldn't get main window")
}
return window
}
}
如果你使用SwiftLint的'first_where'规则,并想静音交战:
UIApplication.shared.windows.first(where: { $0.isKeyWindow })
如果你想在任何ViewController中使用它,那么你可以简单地使用。
self.view.window