preferredStatusBarStyle var not working in iOS12?
Asked Answered
S

7

29

Adding

application.statusBarStyle = .lightContent

to my AppDelegate's didFinishLaunchingWithOptions method nor adding

override var preferredStatusBarStyle: UIStatusBarStyle {
    return UIStatusBarStyle.lightContent
}

to the VC no longer works on iOS12/Xcode10

Any ideas?

Sanative answered 22/9, 2018 at 2:26 Comment(5)
Works fine here, when it should work (i.e. when your view controller is the top-level view controller). You need to describe your situation more fully if you want actual help.Pregnable
Thanks for the response - developing on an iPhone X I'm trying to make the status bar area brighter - for example, the text on the time, the bars on the cellular reception status show up as black, and I have a dark themed UI. I'm using the above-mentioned VC code in the top-level view controller. I'm seeing comments from others saying the same thing about this not working in iOS 12 but it seems to work from you - I'll re-examine.Sanative
Notice that your question never mentioned iPhone X... Hmmm, let me test that particular combination. You’re not in a navigation controller?Pregnable
Yes, I'm in a uinavigationcontroller, the vc is the first one in the stack.Sanative
Your question never mentioned the navigation controller either.Pregnable
P
121

This has nothing to do with iOS 12. You just have the rules wrong.

In a navigation controller situation, the color of the status bar is not determined by the view controller’s preferredStatusBarStyle.

It is determined, amazingly, by the navigation bar’s barStyle. To get light status bar text, say (in your view controller):

self.navigationController?.navigationBar.barStyle = .black

Hard to believe, but true. I got this info directly from Apple, years ago.

You can also perform this setting in the storyboard.

Example! Navigation bar's bar style is .default:

enter image description here

Navigation bar's bar style is .black:

enter image description here

NOTE for iOS 13 This still works in iOS 13 as long as you don't use large titles or UIBarAppearance. But basically you are supposed to stop doing this and let the status bar color be automatic with respect to the user's choice of light or dark mode.

Pregnable answered 22/9, 2018 at 14:18 Comment(11)
Matt, thanks for the responses and the illustrations, very helpful!Sanative
Right but what I'm saying is that it's much better to do this (the right way) than to set UIViewControllerBasedStatusBarAppearance to false.Pregnable
Really nice insight, I always did the accepted answer approach, which was a real pain. I knew the UINavigationController was guilty, but I just didn't stop to figure out why exactly. Thanks for the info @matt, that's sad how Apple simple doesn't mention it anywhere - or at least not clearly in its docs. The status bar is so simple, yet so obscure.Impacted
Thanks - this is absolutely bizarre, surely saved a lot of time thanks to this answer.Staunch
Thanks! Afternoon saverGreenleaf
Been trying out code suggestions on implementing preferredStatusBarStyle. This is the only one that works. Thanks!Whether
Where does one set this for navigation bars in storyboards? I can't seem to find it and it seems my view controller is probably being overwritten by this setting in the storyboardPoulin
Thanks for the bs again Apple! Thanks for this solution matt!Lalia
Is it possible to tie this solution in with Appearance usage and cases when navigation bar is hidden?Arlo
Thanks. But this is so confusing. So, when to use preferredStatusBarStyle?Entomb
Should be in the viewWillAppear +1Cuxhaven
C
37

If you choose a same status bar color for each View Controller:

<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

Ad this to your Info.plist and set status bar color from Project -> Targets -> Status Bar Style by desired color.

On the other hand, in your case, you have a navigation controller which is embedded in a view controller. Therefore, you want to different status bar color for each page.

<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

Ad this to your Info.plist. Then, create a custom class for your NavigationController. After that you can implement the method:

class LightContentNavigationController: UINavigationController {

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

Thats it! Please, inform me whether this was useful!

Cassaundra answered 22/9, 2018 at 13:15 Comment(4)
Someone deleted my comment! I'm putting it back: This resolved my issue, thabks very much - I was missing the entry in my PlistSanative
You really saved my life. Thank you so muchGarrulity
This is the perfect answer. Thanks a lot! Main point is to subclass UINavigationController and not to add the extension of it.Alkalify
I have navigation controllers with hidden navigationbar that work with preferredStatusBarStyle directly, but those that have navigationbar had to have this subclass, tysm!!Marylyn
C
6

If Matt's answer isn't working for you, try adding this line of code before you present your viewController.

viewController.modalPresentationCapturesStatusBarAppearance = true

I encountered a bug where setting modalPresentationStyle to overFullScreen does not give the status bar control to the presented view controller or navigation controller.

Carving answered 26/5, 2021 at 16:40 Comment(1)
This solved my problem, thank you. It's worth pointing out that this also works for PageViewController.Resuscitator
A
3

I was using navigation controller for each tab of UITabBarController. Subclassing UINavigationController and overriding childForStatusBarStyle fixed the issue for me.

class MyNavigationController: UINavigationController {
    open override var childForStatusBarStyle: UIViewController? {
        return topViewController?.childForStatusBarStyle ?? topViewController
    }
}
Aorist answered 27/6, 2021 at 9:25 Comment(0)
S
2

If you have a modal UIViewController the situation becomes very tricky.

Short answer:

  1. Present modal using UIModalPresentationStyle.fullScreen
  2. override preferredStatusBarStyle (in your modal vc)
  3. call setNeedsStatusBarAppearanceUpdate() in viewWillAppear (in your modal vc)

If you don't want to use UIModalPresentationStyle.fullScreen you have to set modalPresentationCapturesStatusBarAppearance

According to apple doc:

When you present a view controller by calling the present(_:animated:completion:) method, status bar appearance control is transferred from the presenting to the presented view controller only if the presented controller's modalPresentationStyle value is UIModalPresentationStyle.fullScreen. By setting this property to true, you specify the presented view controller controls status bar appearance, even though presented non-fullscreen.

The system ignores this property’s value for a view controller presented fullscreen.

Spital answered 2/11, 2021 at 23:0 Comment(1)
unreal. this was hard to find. 👍Crepitate
A
0

You can set

vc.modalPresentationCapturesStatusBarAppearance = true

to make the customization works.

Achromatic answered 10/1, 2022 at 9:7 Comment(0)
H
0

Customizing UINavigationController can fix the issue

class ChangeableStatusBarNavigationController: UINavigationController {

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

Ref: https://serialcoder.dev/text-tutorials/ios-tutorials/change-status-bar-style-in-navigation-controller-based-apps/

Hoashis answered 17/2, 2022 at 7:43 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.