How to change the status bar background color and text color on iOS 13?

Hugo Alonso picture Hugo Alonso · Jun 18, 2019 · Viewed 37.3k times · Source

With the arrival of iOS 13 statusBar's view is no longer accessible trough:

value(forKey: "statusBar") as? UIView

Due to:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '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.'

But it's not clear how it should be used for changing colours as keyWindow?.windowScene?.statusBarManager does not appear to contain anything related to it.

I'm compiling my code with (iOS 10, *) compatibility, so I intend to continue using UIKit.

Any ideas regarding this subject?

Answer

isHidden picture isHidden · Aug 7, 2019

You can add some conditions or use first one. Just create some extension for UIApplication.

extension UIApplication {
var statusBarUIView: UIView? {
    if #available(iOS 13.0, *) {
        let tag = 38482
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

        if let statusBar = keyWindow?.viewWithTag(tag) {
            return statusBar
        } else {
            guard let statusBarFrame = keyWindow?.windowScene?.statusBarManager?.statusBarFrame else { return nil }
            let statusBarView = UIView(frame: statusBarFrame)
            statusBarView.tag = tag
            keyWindow?.addSubview(statusBarView)
            return statusBarView
        }
    } else if responds(to: Selector(("statusBar"))) {
        return value(forKey: "statusBar") as? UIView
    } else {
        return nil
    }
  }
}

UPDATED: Sorry, I don't have enough time to test it in real projects, but it works in "Hello world" app. You can read more info about keyWindow and statusBarFrame in order to make it better.

extension UIApplication {
var statusBarUIView: UIView? {

    if #available(iOS 13.0, *) {
        let tag = 3848245

        let keyWindow = UIApplication.shared.connectedScenes
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows.first

        if let statusBar = keyWindow?.viewWithTag(tag) {
            return statusBar
        } else {
            let height = keyWindow?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
            let statusBarView = UIView(frame: height)
            statusBarView.tag = tag
            statusBarView.layer.zPosition = 999999

            keyWindow?.addSubview(statusBarView)
            return statusBarView
        }

    } else {

        if responds(to: Selector(("statusBar"))) {
            return value(forKey: "statusBar") as? UIView
        }
    }
    return nil
  }
}