iOS SwiftUI首次设备旋转后屏幕尺寸未同步更新问题求助
问题根源
你遇到的异常是因为UIScreen.main.bounds的坐标系是固定的,不会随设备旋转而调整。它的宽高始终以设备竖屏状态为基准,所以无论设备横屏还是竖屏,这个值都不会跟着界面旋转变化。再加上orientationDidChangeNotification的触发时机可能早于界面布局更新,导致首次旋转时尺寸无变化,后续出现宽高颠倒的问题。
另外你自定义的Orientation结构体中使用了强制解包(!),存在潜在崩溃风险,需要优化。
解决方案
方案1:基于UIKit获取当前窗口场景的尺寸
修改监听通知的逻辑,使用UIWindowScene的bounds来获取实时尺寸,同时修复强制解包的问题:
优化后的Orientation结构体
struct Orientation { static var isLandscape: Bool { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return false } return windowScene.interfaceOrientation.isLandscape } static var isPortrait: Bool { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return false } return windowScene.interfaceOrientation.isPortrait } }
修改后的ContentView
struct ContentView: View { var body: some View { VStack { Text("Hello, world!") } .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in // 延迟执行确保界面布局已更新 DispatchQueue.main.async { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return } let screenSize = windowScene.screen.bounds.size var orientation = "Unknown :" if Orientation.isPortrait { orientation = "Portrait :" } else if Orientation.isLandscape { orientation = "Landscape:" } print("\(orientation) width=\(screenSize.width) height=\(screenSize.height)") } } } }
方案2:SwiftUI原生方式(推荐)
利用GeometryReader直接监听视图尺寸变化,符合SwiftUI的响应式设计,无需依赖UIKit通知:
struct ContentView: View { @State private var currentSize = CGSize.zero var body: some View { GeometryReader { proxy in VStack { Text("Hello, world!") Text("当前尺寸:宽\(currentSize.width),高\(currentSize.height)") } .onChange(of: proxy.size) { newSize in currentSize = newSize var orientation = "Unknown :" if Orientation.isPortrait { orientation = "Portrait :" } else if Orientation.isLandscape { orientation = "Landscape:" } print("\(orientation) width=\(currentSize.width) height=\(currentSize.height)") } } } }
验证效果
修改后,设备旋转时会实时输出正确的宽高:
- 竖屏时:
Portrait : width=414.0 height=736.0 - 横屏时:
Landscape: width=736.0 height=414.0 - 再次旋转回竖屏,尺寸会正确回归初始值
内容的提问来源于stack exchange,提问作者bob39722
相关产品推荐
相关产品推荐

