Swift在iOS 9.1中,替代UIScreen.mainScreen().applicationFrame的方法是什么?

19

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

正如标题所说,由于在9.0中已被弃用,那么在UIScreen.mainScreen().applicationFrame之后应该使用什么?

如果可以的话,如果您能提供一个示例或示例,那就太好了,因为我发现苹果的文档很难理解。

目前我使用下面的代码,但我希望将其更改为新版本。期待您的回复!

  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))

1
你可以使用UIScreen.mainScreen().bounds.size。 - user3432164
6个回答

22

使用

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

15

我知道UIScreen.mainScreen().bounds是推荐的替代方案;然而,当您的应用程序没有占据整个屏幕时,特别是在某些iPad上使用Split View和Slide Over功能时,它并不完全等同于UIScreen.mainScreen().applicationFrame

在这种情况下,这是一个很好的替代方案:UIApplication.sharedApplication.keyWindow.frame。(当然,keyWindow必须可用,也就是说,您已经调用了makeKeyAndVisible。)


1
这就是答案。UIScreen.main.bounds在某些情况下不起作用(例如,当您正在通话时)。 - ChrisRockGM
我同意这是正确答案。例如,如果您的应用程序与另一个应用程序并排运行,您可以执行 self.window.frame = UIApplication.shared.keyWindow.boundsself.window.frame = [UIApplication sharedApplication].keyWindow.bounds; 对于 Obj-C,大多数情况下人们在此之后调用 makeKeyAndVisible,但在这种情况下,您必须像 Stepheneye 所说的那样首先执行它,否则您将从 keyWindow 获取 nil 值。 - Jesus Rodriguez

2
从Swift 3开始,现在需要像这样使用它。
let SCREEN_WIDTH = UIScreen.main.bounds.size.width
let SCREEN_HEIGHT = UIScreen.main.bounds.size.height

1

对于:

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

and for:

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

1

很不幸的是UIScreen.mainUIScreen.mainScreen()自iOS 16以来已经被废弃了。

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

通常情况下,苹果文档告诉你不要做什么,但很少给出示例告诉你该怎么做。所以在一番搜索和测试之后,我想出了自己的解决方案。

我创建了一个帮助类,其中包含静态函数,可以让我访问当前场景,从而访问窗口和屏幕。

此解决方案仅适用于单窗口应用程序,例如iOS,并且对于iPad和macOS应用程序需要进行额外的工作。

我的解决方案源于this thread中响应的组合。两个答案都在主应用程序入口中创建了一个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是一个异常常见的对象,建立一个新模式来使用它将会很棒。


0

Swift 3+:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接