如何在iOS 13中查找status bar子视图?
iOS 13 适配获取状态栏视图的正确方案
原实现废弃原因
iOS 13 起系统重构了窗口、状态栏的管理架构,不再将状态栏绑定为UIApplication的全局属性。通过KVC从UIApplication取statusBar的写法,会直接触发系统警告:
App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.
这种写法既无法稳定取到状态栏实例,也会在系统日志中输出违规提示。
适配实现逻辑
- 优先遍历当前App连接的所有窗口场景,筛选出处于前台活跃状态的
UIWindowScene实例 - 从匹配到的活跃场景中获取对应的
statusBarManager对象,这是系统官方提供的状态栏管理入口 - 由于系统未公开
statusBarManager直接暴露状态栏视图的API,需要通过runtime关联的私有字段取值,同时对iOS 13以下的旧版本保留原有取值逻辑做兼容兜底
示例代码
func fetchStatusBarView() -> UIView? { if #available(iOS 13.0, *) { // 遍历所有已连接的窗口场景 for scene in UIApplication.shared.connectedScenes { guard let windowScene = scene as? UIWindowScene, windowScene.activationState == .foregroundActive, let statusBarManager = windowScene.statusBarManager else { continue } // 从statusBarManager中读取关联的底层状态栏视图 return statusBarManager.value(forKey: "_statusBar") as? UIView } return nil } else { // iOS 13以下版本的兼容逻辑 return UIApplication.shared.value(forKey: "statusBar") as? UIView } }
实现注意事项
- 上述读取私有字段的逻辑属于非公开API调用,若仅需要修改状态栏样式、控制状态栏隐藏/显示,优先使用
statusBarManager提供的公开方法,避免不必要的审核风险 - 对支持多窗口的iPadOS应用,不能随意选取任意窗口场景的状态栏,需要匹配用户当前正在交互的前台窗口对应的实例
- 原实现中直接强转
as! UIView的写法存在崩溃风险,建议统一用可选类型接收返回值,增加空判断逻辑提升稳定性
内容的提问来源于stack exchange,提问作者Manish Mahajan
相关产品推荐
相关产品推荐

