SwiftUI中出现'windows'在iOS 15.0中已弃用错误的原因及解决办法(SwiftUI 2.0升级至3.0场景)
嘿,我刚巧碰到过这个问题!升级到SwiftUI 3.0(对应iOS 15+)后遇到这个错误,其实是苹果针对多窗口场景的适配调整导致的,下面给你详细说说:
错误原因
iOS 15开始,UIApplication.shared.windows被标记为废弃,核心原因是:
- 现在iOS系统全面支持多场景(Multi-Scene),比如iPad的分屏多任务、Mac Catalyst的多窗口等,原来的全局
windows数组无法精准定位当前活跃的窗口场景。 - 苹果推荐通过
UIWindowScene.windows来获取对应场景下的窗口,这样能确保拿到的是当前用户正在交互的窗口,适配多场景的复杂情况。
解决思路
这里有几个实用的解决办法,按推荐程度排序:
1. 用SwiftUI原生的@Environment(\.safeAreaInsets)(最推荐)
SwiftUI 3.0已经提供了直接获取安全区边距的环境变量,完全不需要依赖UIKit的窗口对象,更符合声明式编程的风格:
struct YourView: View { // 从环境中获取安全区边距 @Environment(\.safeAreaInsets) private var safeAreaInsets var body: some View { Text("你的内容") .padding(.top, safeAreaInsets.top) } }
2. 通过connectedScenes获取当前活跃窗口
如果还是需要通过UIKit的窗口来获取,可以从UIApplication.shared.connectedScenes中筛选出活跃的窗口场景,再拿到对应的窗口:
// 获取当前活跃窗口的顶部安全区边距 let topInset: CGFloat? = { guard let windowScene = UIApplication.shared.connectedScenes .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene, let window = windowScene.windows.first(where: { $0.isKeyWindow }) else { return nil } return window.safeAreaInsets.top }() // 使用的时候直接传入这个值 .padding(.top, topInset ?? 0)
3. 封装UIApplication扩展方便全局调用
如果你的项目多处需要用到当前窗口,可以写个UIApplication的扩展,封装获取当前活跃窗口的逻辑:
extension UIApplication { /// 获取当前活跃的主窗口 var currentKeyWindow: UIWindow? { connectedScenes .compactMap { $0 as? UIWindowScene } .flatMap { $0.windows } .first { $0.isKeyWindow } } } // 使用时直接调用 let topInset = UIApplication.shared.currentKeyWindow?.safeAreaInsets.top .padding(.top, topInset ?? 0)
内容的提问来源于stack exchange,提问作者user13614484
相关产品推荐
相关产品推荐

