在ios 9.1中使用什么来代替UIScreen.mainScreen().applicationFrame for s



这可能是一个简单的问题,但由于我是初学者,最好问一下。

正如标题所说,我应该使用什么来代替UIScreen.mainScreen().applicationFrame,因为它在9.0中已被弃用。

如果可能的话,如果你能给我一个样本或例子就太好了,因为我觉得苹果的文档很难。

目前我使用以下代码,但我希望将其更改为新版本。我很想听听你的消息!

  let sizeRect = UIScreen.mainScreen().applicationFrame
  let posX = arc4random_uniform(UInt32(sizeRect.size.width))
  let posY = arc4random_uniform(UInt32(sizeRect.size.height))
  Enemy.position = CGPoint(x: CGFloat(posX), y: CGFloat(posY))

使用

let rect1 = UIScreen.mainScreen().bounds // Returns CGRect
let rect2 = UIScreen.mainScreen().bounds.size // Returns CGSize

Swift 3+:

let rect1 = UIScreen.main.bounds // Returns CGRect
let rect2 = UIScreen.main.bounds.size // Returns CGSize

我知道UIScreen.mainScreen().bounds是推荐的替代方案;然而,它并不完全等同于UIScreen.mainScreen().applicationFrame,尤其是当您的应用程序没有占据整个屏幕时,某些iPad上的"拆分视图"one_answers"滑盖"功能会出现这种情况。

在这种情况下,这是一个很好的选择:UIApplication.sharedApplication.keyWindow.frame。(当然keyWindow必须可用,也就是说,您确实调用了makeKeyAndVisible

从swift 3开始,您现在需要这样使用它。

let SCREEN_WIDTH = UIScreen.main.bounds.size.width
let SCREEN_HEIGHT = UIScreen.main.bounds.size.height

用于:

let width = UIScreen.mainScreen().bounds.width

和:

let height = UIScreen.mainScreen().bounds.height

不幸的是,UIScreen.mainUIScreen.mainScreen()自iOS 16以来都已弃用。

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

和往常一样,苹果文档非常善于告诉你不该做什么,但很少给你该做什么的例子。因此,经过一些搜索和测试,我想出了自己的解决方案。

我创建了一个带有静态函数的助手类,使我可以访问当前场景以及窗口和屏幕。

此解决方案仅适用于iOS等单窗口应用程序,并且需要为iPad和macOS应用程序做一些额外的工作。

我的解决方案是从这个线程中的响应组合中派生出来的。两个答案都会在主应用程序条目中创建一个UIWindow?变量。

第一次响应

@main
struct DemoApp: App {
    
    var window: UIWindow? {
        guard let scene = UIApplication.shared.connectedScenes.first,
              let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
              let window = windowSceneDelegate.window else {
            return nil
        }
        return window
    }
    [...]
}

第二次响应

@main
struct TestApp: App {
    var window: UIWindow? {
        guard let scene = UIApplication.shared.connectedScenes.first,
              let windowScene = scene as? UIWindowScene else {
            return nil
        }
    
        return .init(windowScene: windowScene)
    }
}

我不赞成第二个响应,因为它从UIWindowScene创建了一个新的UIWindow。您可以从UIWindowScene访问一组窗口。

我对这个解决方案的第一次尝试是创建一个助手和方便函数,然后用方便函数将它们公开到View上。

助手

struct Application {
    public static var scene: UIScene? {
        guard let scene = UIApplication.shared.connectedScenes.first else {
            return nil
        }
        return scene
    }
    public static var window: UIWindow? {
        
        guard let scene = self.scene,
              let delegate = scene.delegate as? UIWindowSceneDelegate,
              let window = delegate.window else {
            return nil
        }
        
        return window
    }
    public static var screen: UIScreen? {
        guard let window = self.window else {
            return nil
        }
        return window.screen
    }
}

我选择从代表访问UIScene,而不是将UIScene强制转换为UIWindowScene,因为根据苹果针对UIScene的文档,它是:

表示应用程序用户界面的一个实例的对象。

阅读苹果公司UIWindowScene的文档让我相信,通过代表获得它是更可靠的方式。我很好奇在info.plist中使用UISceneConfiguration条目是否更好?

扩展

extension View {
    var scene: UIScene? {
        return Application.scene
    }
    
    var window: UIWindow? {
        return Application.window
    }
    
    var screen: UIScreen? {
        return Application.screen
    }
}

我不是一个经验丰富的Swift开发人员,所以我相信有更好的解决方案。我想知道还有什么更好的解决方案?UIScreen.main似乎是一个非常常见的对象——如果能为它的使用建立一个新的模式,那就太好了。

Swift 3+:

let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.height

最新更新