Har*_*rdy 43 uikit uiwindow uiapplication uiscene
我正在将Core Data和Cloud Kit一起使用,因此必须在应用程序启动期间检查iCloud用户状态。如果出现问题,我想向用户发出一个对话框UIApplication.shared.keyWindow?.rootViewController?.present(...),直到现在我还是这样做。
在Xcode 11 beta 4中,现在有一条新的弃用消息,告诉我:
iOS 13.0中已弃用“ keyWindow”:不应将其用于支持多个场景的应用程序,因为它会返回所有已连接场景的关键窗口
我该如何显示对话框?
Vad*_*vin 47
这是一种向后兼容的检测方式keyWindow:
extension UIWindow {
static var key: UIWindow? {
if #available(iOS 13, *) {
return UIApplication.shared.windows.first { $0.isKeyWindow }
} else {
return UIApplication.shared.keyWindow
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
if let keyWindow = UIWindow.key {
// Do something
}
Run Code Online (Sandbox Code Playgroud)
mat*_*att 41
公认的答案虽然巧妙,但可能过于详尽。您可以更简单地获得完全相同的结果:
UIApplication.shared.windows.filter {$0.isKeyWindow}.first
Run Code Online (Sandbox Code Playgroud)
我还要提醒您,keyWindow不要过分重视弃用。完整的警告消息为:
iOS 13.0中已弃用“ keyWindow”:不应将其用于支持多个场景的应用程序,因为它会返回所有已连接场景的关键窗口
因此,如果您不支持iPad上的多个窗口,则不反对继续使用keyWindow。
iHT*_*boy 37
通常使用
斯威夫特 5
UIApplication.shared.windows.filter {$0.isKeyWindow}.first
Run Code Online (Sandbox Code Playgroud)
另外?在 UIViewController 中:
self.view.window
Run Code Online (Sandbox Code Playgroud)
view.window 是场景的当前窗口
关键窗口
- 手动跟踪窗口
ber*_*rni 33
这是我的解决方案:
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
Run Code Online (Sandbox Code Playgroud)
用法,例如:
keyWindow?.endEditing(true)
Run Code Online (Sandbox Code Playgroud)
use*_*649 23
对于 Objective-C 解决方案
+(UIWindow*)keyWindow
{
UIWindow *foundWindow = nil;
NSArray *windows = [[UIApplication sharedApplication]windows];
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
foundWindow = window;
break;
}
}
return foundWindow;
}
Run Code Online (Sandbox Code Playgroud)
pom*_*mmy 15
在matt的出色回答上略有改进,这甚至更简单,更短且更优雅:
UIApplication.shared.windows.first { $0.isKeyWindow }
Run Code Online (Sandbox Code Playgroud)
Dan*_*orm 12
一个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 })
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
let myKeyWindow: UIWindow? = UIApplication.shared.keyWindowInConnectedScenes
Run Code Online (Sandbox Code Playgroud)
小智 10
为了继续使用与旧版 iOS 版本类似的语法,UIApplication.shared.keyWindow请创建此扩展:
extension UIApplication {
var mainKeyWindow: UIWindow? {
get {
if #available(iOS 13, *) {
return connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }
} else {
return keyWindow
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
if let keyWindow = UIApplication.shared.mainKeyWindow {
// Do Stuff
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,由于它已被弃用,我建议您将窗口存储在 SceneDelegate 中。但是,如果您确实需要临时解决方法,则可以创建一个过滤器并像这样检索 keyWindow。
let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
Run Code Online (Sandbox Code Playgroud)
(在 Xcode 13.2.1 上运行的 iOS 15.2 上进行测试)
extension UIApplication {
var keyWindow: UIWindow? {
// Get connected scenes
return self.connectedScenes
// Keep only active scenes, onscreen and visible to the user
.filter { $0.activationState == .foregroundActive }
// Keep only the first `UIWindowScene`
.first(where: { $0 is UIWindowScene })
// Get its associated windows
.flatMap({ $0 as? UIWindowScene })?.windows
// Finally, keep only the key window
.first(where: \.isKeyWindow)
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想找到UIViewControllerkey 中提供的内容UIWindow,这里是另一个extension您可能会发现有用的:
extension UIApplication {
var keyWindowPresentedController: UIViewController? {
var viewController = self.keyWindow?.rootViewController
// If root `UIViewController` is a `UITabBarController`
if let presentedController = viewController as? UITabBarController {
// Move to selected `UIViewController`
viewController = presentedController.selectedViewController
}
// Go deeper to find the last presented `UIViewController`
while let presentedController = viewController?.presentedViewController {
// If root `UIViewController` is a `UITabBarController`
if let presentedController = presentedController as? UITabBarController {
// Move to selected `UIViewController`
viewController = presentedController.selectedViewController
} else {
// Otherwise, go deeper
viewController = presentedController
}
}
return viewController
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将其放在任何您想要的位置,但我个人将其添加为extensionto UIViewController。
这使我可以添加更多有用的扩展,例如UIViewController更容易呈现的扩展:
extension UIViewController {
func presentInKeyWindow(animated: Bool = true, completion: (() -> Void)? = nil) {
DispatchQueue.main.async {
UIApplication.shared.keyWindow?.rootViewController?
.present(self, animated: animated, completion: completion)
}
}
func presentInKeyWindowPresentedController(animated: Bool = true, completion: (() -> Void)? = nil) {
DispatchQueue.main.async {
UIApplication.shared.keyWindowPresentedController?
.present(self, animated: animated, completion: completion)
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于许多开发人员要求使用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;
}
Run Code Online (Sandbox Code Playgroud)
我在类中创建并添加了此方法AppDelegate作为类方法,并通过下面非常简单的方法使用它。
[AppDelegate keyWindow];
Run Code Online (Sandbox Code Playgroud)
不要忘记在 AppDelegate.h 类中添加此方法,如下所示。
+(UIWindow*)keyWindow;
Run Code Online (Sandbox Code Playgroud)
小智 7
如果你想在任何 ViewController 中使用它,那么你可以简单地使用。
self.view.window
Run Code Online (Sandbox Code Playgroud)
小智 5
尝试这样做:
UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController!.present(alert, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)
对于 Objective-C 解决方案也是如此
@implementation UIWindow (iOS13)
+ (UIWindow*) keyWindow {
NSPredicate *isKeyWindow = [NSPredicate predicateWithFormat:@"isKeyWindow == YES"];
return [[[UIApplication sharedApplication] windows] filteredArrayUsingPredicate:isKeyWindow].firstObject;
}
@end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8426 次 |
| 最近记录: |