在 UIScreen.main 弃用后,在 iOS 上获取屏幕尺寸的正确方法

Luc*_*uca 16 ios swift swiftui

我总是习惯UIScreen.main.bounds.size在 iOS 上获取屏幕尺寸并且工作得很好。

现在(我相信在 iOS 16 中)当我尝试使用 UIScreen 的“主”实例访问屏幕尺寸时,会显示警告:

“main”在 iOS 的未来版本中将被弃用:使用通过上下文找到的 UIScreen 实例代替:即 view.window.windowScene.screen

所以我的问题是:获取屏幕尺寸的正确方法是什么?为简单起见,我们假设我们使用的是 iPhone,因此只有一个屏幕可用。谢谢

eas*_*lee 15

extension UIWindow {
    static var current: UIWindow? {
        for scene in UIApplication.shared.connectedScenes {
            guard let windowScene = scene as? UIWindowScene else { continue }
            for window in windowScene.windows {
                if window.isKeyWindow { return window }
            }
        }
        return nil
    }
}


extension UIScreen {
    static var current: UIScreen? {
        UIWindow.current?.screen
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您就可以在任何地方使用它,就像使用UIScreen.main.

用法

UIScreen.current?.bounds.size
Run Code Online (Sandbox Code Playgroud)


vma*_*njz 2

根据 Apple 关于UIScreen.main弃用的讨论:

Apple 不鼓励使用此符号。请改用通过上下文找到的 UIScreen 实例。例如,通过管理包含视图的窗口的窗口场景上的 screen 属性来引用显示视图的屏幕。

这是通过上下文查找 UIScreen 实例的扩展:

extension UIViewController {
  func screen() -> UIScreen? {
    var parent = self.parent
    var lastParent = parent
    
    while parent != nil {
      lastParent = parent
      parent = parent!.parent
    }
    
    return lastParent?.view.window?.windowScene?.screen
  }
}
Run Code Online (Sandbox Code Playgroud)

作为参考,这是与SceneDelegate 中的UIScreen关联的同一实例:windowScene

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    guard let windowScene = (scene as? UIWindowScene) else { return }
    
    window = UIWindow(frame: windowScene.coordinateSpace.bounds)
    window?.windowScene = windowScene
    window?.rootViewController = ViewController()
    window?.makeKeyAndVisible()
    
    let screen = windowScene.screen
    
    configureNavigationBar()
  }
Run Code Online (Sandbox Code Playgroud)