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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:02:05