preferredStatusBarStyle isn't called

2019-01-01 16:35发布

I followed this thread to override -preferredStatusBarStyle, but it isn't called. Are there any options that I can change to enable it? (I'm using XIBs in my project.)

20条回答
低头抚发
2楼-- · 2019-01-01 16:57

Possible root cause

I had the same problem, and figured out it was happening because I wasn't setting the root view controller in my application window.

The UIViewController in which I had implemented the preferredStatusBarStyle was used in a UITabBarController, which controlled the appearance of the views on the screen.

When I set the root view controller to point to this UITabBarController, the status bar changes started to work correctly, as expected (and the preferredStatusBarStyle method was getting called).

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ... // other view controller loading/setup code

    self.window.rootViewController = rootTabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}

Alternative method (Deprecated in iOS 9)

Alternatively, you can call one of the following methods, as appropriate, in each of your view controllers, depending on its background color, instead of having to use setNeedsStatusBarAppearanceUpdate:

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

or

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];

Note that you'll also need to set UIViewControllerBasedStatusBarAppearance to NO in the plist file if you use this method.

查看更多
宁负流年不负卿
3楼-- · 2019-01-01 16:58

Swift 3 iOS 10 Solution:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
 }
查看更多
美炸的是我
4楼-- · 2019-01-01 17:00

On a UINavigationController, preferredStatusBarStyle is not called because its topViewController is preferred to self. So, to get preferredStatusBarStyle called on an UINavigationController, you need to change its childViewControllerForStatusBarStyle.

To do it for one UINavigationController (my recommendation):

class MyRootNavigationController: UINavigationController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    override var childViewControllerForStatusBarStyle: UIViewController? {
        return nil
    }
}

To do it for all UINavigationController (warning: it affects UIDocumentPickerViewController, UIImagePickerController, etc.):

extension UINavigationController {
    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return nil
    }
}
查看更多
十年一品温如言
5楼-- · 2019-01-01 17:03

So I actually added a category to UINavigationController but used the methods:

-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;

and had those return the current visible UIViewController. That lets the current visible view controller set its own preferred style/visibility.

Here's a complete code snippet for it:

In Swift:

extension UINavigationController {

    public override func childViewControllerForStatusBarHidden() -> UIViewController? {
        return self.topViewController
    }

    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return self.topViewController
    }
}

In Objective-C:

@interface UINavigationController (StatusBarStyle)

@end

@implementation UINavigationController (StatusBarStyle)

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

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

@end

And for good measure, here's how it's implemented then in a UIViewController:

In Swift

override public func preferredStatusBarStyle() -> UIStatusBarStyle {
    return .LightContent
}

override func prefersStatusBarHidden() -> Bool {
    return false
}

In Objective-C

-(UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent; // your own style
}

- (BOOL)prefersStatusBarHidden {
    return NO; // your own visibility code
}

Finally, make sure your app plist does NOT have the "View controller-based status bar appearance" set to NO. Either delete that line or set it to YES (which I believe is the default now for iOS 7?)

查看更多
看风景的人
6楼-- · 2019-01-01 17:03

The NavigationController or TabBarController are the ones that need to provide the style. Here is how I solved: https://stackoverflow.com/a/39072526/242769

查看更多
笑指拈花
7楼-- · 2019-01-01 17:04

In Swift for any kind of UIViewController:

In your AppDelegate set:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    window!.rootViewController = myRootController
    return true
}

myRootController can be any kind of UIViewController, e.g. UITabBarController or UINavigationController.

Then, override this root controller like this:

class RootController: UIViewController {
    override func preferredStatusBarStyle() -> UIStatusBarStyle {
        return .LightContent
    }
}

This will change the appearance of the status bar in your whole app, because the root controller is solely responsible for the status bar appearance.

Remember to set the property View controller-based status bar appearance to YES in your Info.plist to make this work (which is the default).

查看更多
登录 后发表回答