Updating the status bar style between view controllers

There is a property in Info.plist file called View controller-based status bar appearance. It should be set to YES. Then in your UIViewController you should override preferredStatusBarStyle:

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

Here is one important thing to notice: if you have view controllers embedded into UINavigationController and your view controller's preferredStatusBarStyle method not getting called - you will have to workaround it by writing something like following:

extension UINavigationController {
    override open var preferredStatusBarStyle : UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle ?? .default
    }
}

What it does is simply asking top controller for it's statusbar style, and update appropriately


There is a great deal of misunderstanding promulgated about how to govern the status bar style when your view controller is a child of a navigation controller.

Your child view controllers can implement preferredStatusBarStyle, and this will work correctly if the navigation bar is hidden.

If the navigation bar is showing, the navigation controller sets the status bar style based on the navigation bar's barStyle — to .default if the bar style is .default, and to .lightContent if the bar style is .black. So the correct way for your view controller to set the status bar style, when the navigation bar is showing, is to set the navigation controller's navigation bar style.

The obvious place to do this is in viewWillAppear, which is called whenever this view controller becomes the top of the navigation controller's stack:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.barStyle = .black // or .default
}