如何在 iOS 15 上使用 UIWindowScene.windows?

maj*_*451 4 swift swiftui uiwindowscene ios15

目前,在 iOS 14.6 中,我可以使用以下代码在我的应用程序中调用一个显示共享表的函数:

func share(link: URL) {
    let activityView = UIActivityViewController(activityItems: [link], applicationActivities: nil)
    UIApplication.shared.windows.first?.rootViewController?.present(activityView, animated: true, completion: nil)
}
Run Code Online (Sandbox Code Playgroud)

自 iOS 15 测试版以来,Xcode 告诉我“'windows' 在 iOS 15.0 中已弃用:在相关的窗口场景中使用 UIWindowScene.windows”。我如何更新它,以便我的共享表可以在这个新版本中正常工作?谢谢!

Rém*_* B. 103

(在 Xcode 13.2.1 上运行的 iOS 15.2 上进行测试)

改进Rachid 的答案,这是一个Swiftier 版本

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)

  • 我们费尽千辛万苦才拿到窗户,真是太疯狂了 (7认同)
  • 对我来说,我必须删除行 `.filter { $0.activationState == .foregroundActive }` 才能使其正常工作。可以在这里找到更好的工作解决方案:/sf/answers/4062232821/ (4认同)
  • 我正在运行 iOS 15.2,并且添加了两个扩展,但 xCode 中仍然出现警告:“'windows' 在 iOS 15.0 中已弃用:请在相关窗口场景上使用 UIWindowScene.windows。” 我究竟做错了什么? (2认同)
  • 您可以从“keyWindow” getter 中省略“UIApplication.shared”,因为“UIApplication”是单例,因此,当您访问“UIApplication.shared.keyWindow”时,您已经可以从 getter 中访问“connectedScenes”。 (2认同)

Rac*_*hid 7

这对我有用并且没有产生任何警告:

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)

来源:https : //newbedev.com/how-to-resolve-keywindow-was-deprecated-in-ios-13-0