How to change iOS status bar color in child view controller

By default, it seems that UINavigationController unfortunately doesn't provide a sensible default implementation of childViewControllerForStatusBarStyle. By implementing this method, you can tell your navigationController to defer all calls to preferredStatusBarStyle to its topmost childViewController.

You could either subclass UINavigationController and implement the method there, or simply add a category:

@implementation UINavigationController (ChildStatusBarStyle)

- (UIViewController *)childViewControllerForStatusBarStyle 
{
    return self.topViewController;
}

@end

I just find out: When you embed the root view controller inside UINavigationController correctly, You'd never need to create a category to expand the capability of navigation controller, or subclassing UINavigationController for the same purpose.

You just need to put preferredStatusBarStyle inside every view controller, and remember to call [self setNeedsStatusBarAppearanceUpdate]; to update status bar style. Simple as it is!

check out this video from WWDC 2013: Click Here


EDIT:

The reason I made it working, is I happen to set UINavigationBar hidden. In this case, it behaves the same when not using UINavigationController at all. When you Trying to change StatusBarStyle of an UIViewController which is inside UINavigationController stack. It will fail to work in this way. It only works in individual UIViewController. The WWDC 2013 Video example is not using UINavigationController, so that why the approach is working fine.


James Frost answer was the only one that worked for me. Thank you! Here's a Swift 4 version of that code.

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

Note: this is a bit unwieldy as-is, I recommend adding some code to limit its scope to a single viewController. Something like this:

extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
    if topViewController is MyViewController {
        return topViewController
    } else {
        return nil
    }
}
}

You'll obviously need to replace MyViewController with your UIViewController subclass that implements preferredStatusBarStyle.

override var preferredStatusBarStyle: UIStatusBarStyle {
    if isBackgroundDark() {
        return .lightContent
    } else {
        return .default
    }
}

Again isBackgroundDark() is yours to implement.

Finally don't forget to call setNeedsStatusBarAppearanceUpdate() in your viewController every time isBackgroundDark() changes its value.