3

I am able to hide the status bar on the launch screen by setting Status bar is initially hidden to YES in Info.plist and then I want to show it on my first view controller with a .lightContent style.

However UIApplication.shared.statusBarStyle = .lightContent is deprecated since iOS 9 (so I don't want to use it) and using the following code give me a black status bar on my first view controller.

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

How can I change the status bar style when my first view controller load?

I am trying to find a global solution like UIApplication.shared.statusBarStyle = .lightContent since I don't really want to set the status bar style for every view controller. I have tested the solutions with View controller-based status bar appearance set to YES and NO.

adrgrondin
  • 648
  • 7
  • 17
  • https://stackoverflow.com/questions/38740648/how-to-set-status-bar-style-in-swift-3 – JonJ Sep 19 '18 at 08:20
  • Already tried all the solutions but my status bar stay black and I don't want to use the deprecated solution. I am also not sure if the 'hack' solution is good to use. – adrgrondin Sep 19 '18 at 08:27
  • 1
    Is your first view controller nested inside a UINavigationController? The UINavgationController is known to not ask its childController for the `preferredStatusBarStyle` property – Frederik Sep 19 '18 at 08:30
  • @Frederik yes it is, I did not think about that. Do you know how I can change the status bar style of a view controller nested in a navigation controller? – adrgrondin Sep 19 '18 at 08:31
  • 1
    @adrgrondin Off the top of my head, one way is to subclass the `UINavigationController` and override its `preferredStatusBarStyle` property to delegate onto the `topViewController`. This is not the most elegant solution, but the only one I can think of right now. – Frederik Sep 19 '18 at 08:36
  • @Frederik thank you for this first way to do it! I will try it and try to see if I can find other ways to do it since I now know where the problem is. – adrgrondin Sep 19 '18 at 08:39
  • 1
    @Frederik is correct. Just to add, though, you don't need to subclass `UINavigationController` to achieve this; you can add an extension to `UINavigationController` which overrides `prefersStatusBarHidden` and `preferredStatusBarStyle`. That should work fine (as long as you set `View controller-based status bar appearance` to `YES` in your info.plist). – Pete Morris Sep 19 '18 at 09:05
  • @PeteMorris thank you for this, all will try that! – adrgrondin Sep 19 '18 at 09:21
  • It now works, I used the extension approach! You can answer the question or I can answer it, explain the problem and how to solve it. – adrgrondin Sep 19 '18 at 09:39
  • @PeteMorris Nice touch, I wasn't aware that you could override the instance property in an extension. @adrgrondin Another solution, if you don't need the different view controllers inside the navigation controller to change the status bar, i.e. if you only need the `.lightContent` in your app, you can change the `barStyle` on the UINavigationBar to be `.black` and then change the `barTintColor` to your preferred colour, in order to achieve the same. This can be done in the storyboard, if you use that. – Frederik Sep 19 '18 at 13:28
  • @Frederik thank you for this other approach! – adrgrondin Sep 19 '18 at 14:11

1 Answers1

11

The problem you're experiencing is that UINavigationController doesn't defer the choice of status bar to its view controllers.

Instead, for a navigation controller, the status bar style can be set by adjusting the barStyle property of its navigationBar.

If it is set to a black style, then the status bar will be light style:

navigationController?.navigationBar.barStyle = .black

Note, that this will also change the color of the navigationBar, however you can still set the bar's colour to whatever you want using barTintColor:

navigationController?.navigationBar.barTintColor = .purple

If you want to make a global change, so that all instances of UINavigationController use the same status bar style (useful if you've got multiple tabs all of which use a navigation controller), then you can add an extension on UINavigationController and override the preferredStatusBarStyle property:

extension UINavigationController {
    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

A final option, is to defer the choice to the view controllers in the navigation controller's stack.

To do that, override the childViewControllerForStatusBarStyle property of your navigation controller extension and have it return the topViewController:

extension UINavigationController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return topViewController
    }
}

In this case, you'll need to override preferredStatusBarStyle in all of your view controllers (not the optimal approach, but it's an option if you need this granular level of control on a per-child-controller basis).

All of these solutions require that your View controller-based status bar appearance key in Info.plist is set to YES.

Pete Morris
  • 1,472
  • 8
  • 13