25

I need to update status bar style on every view controller based on the background color (what UINavigationController is doing automatically).

Have tried all the options described on stackoverflow (View controller-based status bar appearance in info.plist set to YES), but none worked for me.

I am using Xcode 10 beta 6 and Swift 4.2, targeting iOS 12.

Tomáš Pánik
  • 556
  • 1
  • 5
  • 18
  • Possible duplicate of [Setting statusbarStyle (deprecated in iOS 9.0)](https://stackoverflow.com/questions/50693665/setting-statusbarstyle-deprecated-in-ios-9-0) – Jacob Ahlberg Nov 01 '18 at 17:28

6 Answers6

33

Swift 4+, iOS 12+

View controller-based status bar appearance now needs to be set to YES in info.plist since UIKit no longer wants us to edit status bar style through UIApplication.shared—status bar style is now view-controller based.

Then if you want the change to be applied at app level, simply override preferredStatusBarStyle in the appropriate container view controller (ideally the root)...

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

...and this will propagate to all view controllers underneath it. And if you want to edit status bar style per view controller, apply this override per view controller.

If status bar style ever changes during runtime, then you need to call setNeedsStatusBarAppearanceUpdate() (from anywhere in the container/root view controller or that specific view controller), otherwise it isn't needed.

trndjc
  • 11,654
  • 3
  • 38
  • 51
  • This! All other answers regarding setting `View controller-based status bar appearance` to `NO` **WILL NOT WORK**. – Caio Nov 07 '18 at 18:16
  • I use custom transitions between View Controllers. Since iOS 12 animation of the status bar is broken, I used a smooth transition from light to default and vice-versa. In iOS 12 status bar blinks for short time before a transition. Do you know what has been changed? – Evgeny Nov 09 '18 at 10:30
  • And, if the UIApplication's rootViewController is a tabbarvc or navigationvc(container view controller), then this vc will take over the control, you can override `childViewControllerForStatusBarStyle` method and return the controller which you want to take over the control. For example, the tabbar returns `selectedViewController`(navigationvc), and the navigationvc returns its `topViewController`. – Jiangshi Fresh Aug 13 '20 at 05:41
29

Set View controller-based status bar appearance to NO in the info.plist and override preferredStatusBarStyle in each view controller like so:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

And call setNeedsStatusBarAppearanceUpdate() in your view controller (in viewDidLoad() for example).

ielyamani
  • 17,807
  • 10
  • 55
  • 90
  • 1
    You are right! But that's being deprecated since iOS 9. But did I miss something? I set the value to info.plist. Then added this line to viewDidLoad() of particular view controller. No visible changes. – Tomáš Pánik Sep 08 '18 at 18:36
  • @TomášPánik are you calling `self.setNeedsStatusBarAppearanceUpdate()`? – ielyamani Sep 08 '18 at 18:37
  • sure. xcode telling me "setter for 'statusBarStyle' was deprecated in iOS 9.0: use `-[UIViewController prefferedStatusBarStyle]`". do you know how to it? note that I am getring another error "property does not override any property from it's superclass" for some reason, while using `override var prefferedStatusBarStyle ...` – Tomáš Pánik Sep 08 '18 at 18:49
  • error "method does not override any method from its superclass" – Tomáš Pánik Sep 09 '18 at 10:16
  • @TomášPánik are you using it in a UIViewController? – ielyamani Sep 09 '18 at 10:19
  • ofc. `class blabla: UIViewController` – Tomáš Pánik Sep 09 '18 at 10:23
  • I can pull this project to my github if you are curious whats wrong with it just like me :D – Tomáš Pánik Sep 09 '18 at 10:25
  • not working with override at all. I am pulling to github, give me 2 minutes – Tomáš Pánik Sep 09 '18 at 10:27
  • edit: works now on both projects; I had to miss something, I believe I've tried this as well -.- – Tomáš Pánik Sep 09 '18 at 10:33
  • 8
    note: this method works with plist boolean set to YES – Tomáš Pánik Sep 09 '18 at 10:36
  • you can search the other answers regarding this :) thanks a lot I don't know what was wrong when I was trying all the answers from stackoverflow, but now it works :) – Tomáš Pánik Sep 09 '18 at 10:38
  • Glad I could help! – ielyamani Sep 09 '18 at 10:39
  • 4
    If using a modally presented view controller you may need to set `myViewController.modalPresentationCapturesStatusBarAppearance = true` on the view controller to be presented modally. I could not get this answer to work unless I did this. The `info.plist` key was set to `yes`. – Chris Nov 08 '18 at 21:31
15

If you have View controller-based status bar appearance in info.plist set to YES and your view controller is embedded into UINavigationController, then your navigation controller will be responsible for updating bar style (through navigationController.navigationBar.barStyle) and preferredStatusBarStyle property will be ignored

swearwolf
  • 327
  • 3
  • 10
11

I have Xcode 10.2 and found as you did that setting the View controller-based status bar appearance in info.plist to "YES" will not change the status bar style at all.

However, I did find that changing two keys in the info.plist file will do all the work of changing the status bar to light or dark without any additional coding.

Here's what I did to fix it for myself
When hovering over the top line "Information Property List" from the info.plist file, a small round "+" button will appear. Click this button and scroll through the items until you find the following keys.

View controller-based status bar appearance [set this value to] NO
Status bar style [set this value to] UIStatusBarStyleLightContent

NOTE: The UIStatusBarStyleLightContent is not found as a selectable item in the value list and must be typed into the value box.

info.plist

I hope this helps you or anyone else looking for an answer to this question.

Jim Bray
  • 758
  • 8
  • 12
  • 1
    But will UIStatusBarStyleLightContent change the statusbar color on every ViewController based on the content? – Tomáš Pánik Apr 12 '19 at 17:12
  • 1
    Oh wow, I didn't see that part in the question LOL, Looks like I need to pay more attention to the questions here. No, it does not change them based on content. It will just change them for the whole project. Thanks for pointing that out!. – Jim Bray Apr 12 '19 at 19:41
2

If you're wrapped in a nav controller, you're going to need this:

final class LightNavigationController: UINavigationController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}
thexande
  • 1,645
  • 16
  • 23
-1
override func viewDidLoad(){
    super.viewDidLoad()

    navigationController?.navigationBar.barStyle = .default
}

override var prefersStatusBarHidden: Bool {
    return true
}

I applied scroll view also in the same screen, by this code was able to resolve status bar issue.

Deviyani Swami
  • 749
  • 8
  • 17