You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIScreen.main已废弃,SwiftUI中获取屏幕宽高该用什么替代?

iOS 16+ SwiftUI 获取屏幕尺寸的替代方案(替代废弃的UIScreen.main)

在iOS 16及以后,UIScreen.main.bounds被标记为废弃,苹果推荐用更适配SwiftUI布局体系的方法获取屏幕或容器尺寸,以下是几种可行方案:

1. 使用GeometryReader(SwiftUI原生常用方式)

GeometryReader能直接获取父容器的尺寸,要是你需要当前显示屏幕的尺寸(忽略安全区域),把它放在根视图层级,配合ignoresSafeArea()用就行。

示例代码:

struct ContentView: View {
    var body: some View {
        GeometryReader { geometry in
            Text("屏幕宽度:\(geometry.size.width),高度:\(geometry.size.height)")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .ignoresSafeArea()
    }
}

这种方式完全贴合SwiftUI的布局上下文,设备旋转、分屏时尺寸会自动更新。

2. 利用iOS 16新增的环境变量DisplaySize

iOS 16专门加了DisplaySize环境值,直接就能读取当前设备的物理屏幕尺寸,不用依赖UIKit。

示例代码:

struct ContentView: View {
    @Environment(\.displaySize) private var displaySize
    
    var body: some View {
        Text("屏幕宽度:\(displaySize.width),高度:\(displaySize.height)")
    }
}

这个环境值返回的是设备物理屏幕的固定尺寸,不受安全区域、分屏等布局变化影响,适合需要固定屏幕尺寸的场景。

3. 适配原有全局变量的实现

要是你想保留全局变量的形式,有两种方式:

方式1:用UIKit新APIdisplayBounds

苹果提供了UIScreen.main.displayBounds替代原来的bounds,直接替换原有代码就行:

import SwiftUI

let width = UIScreen.main.displayBounds.width
let height = UIScreen.main.displayBounds.height

方式2:纯SwiftUI全局获取

在App启动时通过根视图获取尺寸并存到全局变量,同时处理设备旋转的更新:

import SwiftUI

var screenWidth: CGFloat = 0
var screenHeight: CGFloat = 0

@main
struct YourApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear { updateScreenSize() }
                .onRotate { _ in updateScreenSize() }
        }
    }
    
    private func updateScreenSize() {
        let window = UIApplication.shared.windows.first
        screenWidth = window?.screen.displayBounds.width ?? 0
        screenHeight = window?.screen.displayBounds.height ?? 0
    }
}

// 扩展View添加旋转监听
extension View {
    func onRotate(perform action: @escaping () -> Void) -> some View {
        self.modifier(RotationModifier(action: action))
    }
}

struct RotationModifier: ViewModifier {
    let action: () -> Void
    
    func body(content: Content) -> some View {
        content
            .onAppear {
                UIDevice.current.beginGeneratingDeviceOrientationNotifications()
                NotificationCenter.default.addObserver(
                    forName: UIDevice.orientationDidChangeNotification,
                    object: nil,
                    queue: .main
                ) { _ in action() }
            }
            .onDisappear {
                UIDevice.current.endGeneratingDeviceOrientationNotifications()
                NotificationCenter.default.removeObserver(self)
            }
    }
}

内容的提问来源于stack exchange,提问作者Abraham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:10:33