14
votes

So I used to use:

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent 
                                            animated:YES];

to animate the status bar style change, from dark to light and vice versa

However this method is deprecated since iOS 9.

I do changed to use preferredStatusBarStyle following @serenn's answer in preferredStatusBarStyle isn't called

It indeed can change the status bar style in old fashion, but without animations.

The documentation said:

If the return value from this method changes, call the setNeedsStatusBarAppearanceUpdate method.

However I have no idea where to call it, I tried put it in viewWillAppear, but no luck.

preferredStatusBarUpdateAnimation remains as default:UIStatusBarAnimationFade

So I am confused. Looking for answers for how to animate as the deprecated method. Thanks in advance!

1

1 Answers

18
votes

OK I have spent two hours searching and trying, figured it out:

First, you have to make sure your child view controller can control the status bar style in the navigation controller by overriding preferredStatusBarStyle like @serenn's answer in preferredStatusBarStyle isn't called

In order to have animation, I have to return two different style before and after the view controller appears like below:

-(UIStatusBarStyle)preferredStatusBarStyle {
    if (!viewAppeared)
        return UIStatusBarStyleDefault;
    else
        return UIStatusBarStyleLightContent; // your own style
}

viewAppeared is a BOOL to indicate if the viewWillAppear is called:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    viewAppeared = YES;

    [UIView animateWithDuration:0.8 animations:^{
        [self setNeedsStatusBarAppearanceUpdate];
    }];
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    viewAppeared = NO;
}

So when the view controller does not appear, the status bar style is UIStatusBarStyleDefault and will be changed to UIStatusBarStyleLightContent in viewWillAppear.

Then call setNeedsStatusBarAppearanceUpdate to update the change like below, be noted animateWithDuration is a must to have animation.

[UIView animateWithDuration:0.8 animations:^{
    [self setNeedsStatusBarAppearanceUpdate];
}];

I used to find out you don't have to call preferredStatusBarStyle first like below, setNeedsStatusBarAppearanceUpdate will invoke preferredStatusBarStyle again:

[UIView animateWithDuration:0.8 animations:^{
    [self preferredStatusBarStyle];
    [self setNeedsStatusBarAppearanceUpdate];
}];

Though this solution solve the problem, I don't choose to use it for now. I can have the same result with only one line code but it is now way too many of the code I have to write. The deprecated API does not even trigger a warning right now, so until Apple keeps pushing me to change, I will not use this way. When the time comes I hope there is a good solution then.

I am very confused why Apple deprecated the one-line code ([UIApplication sharedApplication] setStatusBarStyle]...)that can do all the tricks, but use a more complicated to achieve the same result. Even you want to give more fine-grained control, Apple does not have to deprecated the old one.

But maybe I just didn't find the best one right now. Hope someone could enlight me.