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

SwiftUI中出现'windows'在iOS 15.0中已弃用错误的原因及解决办法(SwiftUI 2.0升级至3.0场景)

解决SwiftUI 3.0中UIApplication.shared.windows废弃的问题

嘿,我刚巧碰到过这个问题!升级到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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 16:09:08