The correct way to set a light status bar text color in iOS 7 based on different ViewControllers

后端 未结 8 1233
死守一世寂寞
死守一世寂寞 2020-12-25 14:52

I need to let a specific ViewController embedded in an UINavigationController to have light status bar text color (but other ViewControllers to beh

相关标签:
8条回答
  • 2020-12-25 15:03

    Here's an improvement to Groot answer, in form of a simple category to UINavigationController, without the need to subclass UINavigationController.

    Swift

    extension UINavigationController {
        override public func preferredStatusBarStyle() -> UIStatusBarStyle {
            return topViewController?.preferredStatusBarStyle() ?? .Default
        }
    }
    

    Swift 3 & Swift 4

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

    Objective-C

    @implementation UINavigationController (StatusBarStyle)
    
    - (UIStatusBarStyle)preferredStatusBarStyle 
    {
        return [self.topViewController preferredStatusBarStyle];
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-25 15:09

    I used the first method you mentioned, I also found there's kinda bug when you used UINavigationController, it will never pass preferredStatusBarStyle call to it's child view controllers. What I have done is subclass the UINavigationController, and override preferredStatusBarStyle method as follows:

    @implementation GLBaseNavigationController
    
    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        UIViewController *lastViewController = [self.viewControllers lastObject];
        if ([lastViewController respondsToSelector:@selector(preferredStatusBarStyle)]) {
            return [lastViewController preferredStatusBarStyle];
        } else if ([super respondsToSelector:@selector(preferredStatusBarStyle)]) {
            return [super preferredStatusBarStyle];
        }
        return UIStatusBarStyleDefault;
    }
    

    Then whenever I need a navigation controller, I use GLBaseNavigationController instead of UINavigationController. For storyboards, you need to specify the class of the navigation controller to your subclass as well.

    0 讨论(0)
  • 2020-12-25 15:11

    To set UIStatusBarStyle individually for each UIViewController on UINavigationController stack you have to first subclass your UINavigationController and override childViewControllerForStatusBarStyle method.

    In your UINavigationController subclass add:

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

    than you can set UIStatusBarStyle to whatever you want in every UIViewController using preferredStatusBarStyle method. Eg:

    -(UIStatusBarStyle)preferredStatusBarStyle {
         return UIStatusBarStyleLightContent;
    }
    
    0 讨论(0)
  • 2020-12-25 15:11

    For your first solution, I don't think you can change the status bar in viewDidLoad. If you have two ViewControllers stacked on top of each other, and each one toggles the status bar differently, that method will only get called once for each. You really want to change the status bar in viewWillAppear so that it gets called each time the page is shown. I also don't think you can rely on preferredStatusBarStyle since I'm also not sure how often/when that gets called. This is how you want to do it:

    - (void) viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
    
        [self.navigationController.navigationBar setBarStyle:UIBarStyleDefault];
    }
    
    0 讨论(0)
  • 2020-12-25 15:17

    iOS 13 Solution(s)

    Regarding your attempt #3 - DEPRECATED

    UIApplication.setStatusBarStyle(_:animated:) has been deprecated since iOS 9. According to Apple,

    In iOS 7 and later, status bar behavior is determined by view controllers, and so calling this method has no effect by default. When view controller-based status bar appearance is disabled, this method behaves normally. To opt out of the view controller-based status bar appearance behavior, you must add the UIViewControllerBasedStatusBarAppearance key with a value of false to your app’s Info.plist file, but doing so is not recommended.

    Regarding your attempt #2 - LEGACY

    Setting the barStyle property is now (iOS 13+) considered a "legacy customization." According to Apple,

    In iOS 13 and later, customize your navigation bar using the standardAppearance, compactAppearance, and scrollEdgeAppearance properties. You may continue to use these legacy accessors to customize your navigation bar's appearance directly, but you must update the appearance for different bar configurations yourself.

    Regarding your attempt #1 - You were on the right track!

    UINavigationController is a subclass of UIViewController (who knew

    0 讨论(0)
  • 2020-12-25 15:19

    In your AppDelegate didFinishLaunch method, set the default status bar style, say:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault
                                                    animated:YES];       
        return YES;
    }
    

    Then, in your those two view controllers, where you want to change status bar, override following methods:

    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated]        
    
        // Here change status bar color
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent
                                                    animated:YES];       
    
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear]                
    
        // Here bring back to color, that we set in AppDelegate
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault
                                                    animated:YES];       
    }
    
    0 讨论(0)
提交回复
热议问题