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
相关产品推荐
相关产品推荐

