iOS纯代码UI:添加覆盖状态栏的LoaderOverlay且保留状态栏文字
解决LoaderOverlay显示时状态栏文字消失的问题
我来帮你搞定这个状态栏文字消失的坑!咱们先分析问题根源,再一步步修正:
问题核心
- 你用的
UIApplication的statusBarView扩展依赖私有API("statusBar"这个key),iOS 13之后系统对状态栏结构做了调整,这种写法不仅不安全(可能过不了App Store审核),还会和你设置的窗口层级冲突。 - 你把
window.windowLevel改成UIWindow.Level.statusBar,会让Loader窗口直接覆盖在状态栏窗口之上,导致状态栏文字被完全遮挡。
解决方案步骤
1. 废弃私有API的状态栏背景设置
首先删掉setupNavigationBarStyle里的UIApplication.shared.statusBarView!.backgroundColor代码,同时移除那个UIApplication的statusBarView扩展。
因为你已经把UINavigationBar的isTranslucent设为false,状态栏会自动继承导航栏的barTintColor,不需要额外设置背景色。修改后的代码如下:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { setupNavigationBarStyle() window = UIWindow(frame: UIScreen.main.bounds) window?.makeKeyAndVisible() window?.rootViewController = UINavigationController(rootViewController: HeadlinesViewController(networkHelper: NetworkHelper.shared)) return true } func setupNavigationBarStyle() { // 移除statusBarView相关私有API代码 UINavigationBar.appearance().barTintColor = UIColor.navigationBarBackground UINavigationBar.appearance().tintColor = UIColor.navigationBarTint UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.navigationBarText] UINavigationBar.appearance().isTranslucent = false UITabBar.appearance().barTintColor = UIColor.navigationBarBackground UITabBar.appearance().tintColor = UIColor.navigationBarTint // 可选:调整状态栏文字颜色,根据导航栏背景色选择 UINavigationBar.appearance().barStyle = .darkContent // 浅色背景用这个,深色背景用.default }
2. 修改LoaderOverlay实现,避免修改窗口层级
不要直接操作window的层级,而是把Overlay添加到当前根控制器的view上,这样既能覆盖全屏(包括状态栏区域),又不会遮挡状态栏文字。修改后的LoaderOverlay代码:
public class LoaderOverlay{ var overlayView = UIView() var activityIndicator = UIActivityIndicatorView() class var shared: LoaderOverlay { struct Static { static let instance:LoaderOverlay = LoaderOverlay() } return Static.instance } public func showOverlay() { // 获取当前窗口的根控制器视图 guard let rootView = UIApplication.shared.keyWindow?.rootViewController?.view else { return } overlayView.removeFromSuperview() // 先移除旧的overlay,避免重复添加 overlayView = UIView(frame: rootView.bounds) overlayView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5) // 设置自动适配父视图尺寸变化 overlayView.autoresizingMask = [.flexibleWidth, .flexibleHeight] activityIndicator.removeFromSuperview() activityIndicator = UIActivityIndicatorView(style: .whiteLarge) activityIndicator.center = overlayView.center overlayView.addSubview(activityIndicator) activityIndicator.startAnimating() rootView.addSubview(overlayView) // 把overlay放到最上层,确保覆盖所有内容 rootView.bringSubviewToFront(overlayView) } public func hideOverlayView() { activityIndicator.stopAnimating() overlayView.removeFromSuperview() } }
为什么这样改?
- 不再依赖私有API,避免审核风险,同时适配iOS 13+的系统变化。
- 把Overlay添加到根控制器的view层级中,和状态栏属于同一window,不会覆盖状态栏的文字层;同时因为导航栏不透明,Overlay可以延伸到状态栏区域,完美实现你要的全屏覆盖效果。
内容的提问来源于stack exchange,提问作者Reimond Hill
相关产品推荐
相关产品推荐

