Status bar throwing tantrums in iOS 9+

If your app supports iOS 9+ & you have modified the status bar styling using..

UIApplication.shared.setStatusBarStyle(
.lightContent,
animated: true
)

..then you must have seen the above warning saying its deprecated! As always it also suggests us to use the alternate new method which is..

override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}

If you haven’t used this yet then lets talk about it else you can jump to the next section where I have discussed how it can throw tantrums in some cases 😒

preferredStatusBarStyle is a new var on UIViewController. It has to be overriden in your custom view-controller which means that here you can control the styling of its status bar, black or white 👍. This property gets called whenever your controller gets loaded.

In some cases your controller may want to update its status bar styling again depending on some condition like how much you have scrolled or something. In such cases you can call..

setNeedsStatusBarAppearanceUpdate()

This method forces iOS to update its status bar and in the process it will call preferredStatusBarStyle again 👍. So you can force iOS to update its status bar as per your need as well 😊

All looks good right ? 😈

There’s one case where this won’t work and that is if your controller is embedded in a navigation stack 😒. Reason being that iOS wants the parent controller (and NOT the child controller) to decide what kind of status bar one needs to show! Lets see what happens in such cases..

  • child controller’s preferredStatusBarStyle WON’T get called
  • its parent navigation-controller’s preferredStatusBarStyle will get called

Now don’t worry you don’t have to subclass UINavigationController to handle status bar updates. Rather we can leverage extensions to our rescue 😎.

You can simply add the following logic in your code base..

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

..this logic simply means that you are asking the navigation stack’s topViewController to make the decision of what kind of status bar you need to show where topViewController is nothing but your current controller on screen! This way you can still handle your updates in your current controller 🚀

Not sure why apple decided to do it this way but we have to deal with it 😅