Hiding Navigation Bar and Status Bar with Animation on iOS

In iOS 7 Apple changed the way a status bar is laid out in the view hierarchy. Mainly, UINavigationController's navigationBar is pinned to the status bar, so when the status bar is hidden the position of the navigation bar changes. It means that when we want to simultaneously hide both these elements, we have to perform the operations in the correct order.

Here's how we can do that:

@interface ViewController()
@property (nonatomic, getter = isStatusBarHidden) BOOL statusBarHidden;
@end

@implementation ViewController

#pragma mark - UIViewController

- (BOOL)prefersStatusBarHidden
{
    return self.isStatusBarHidden;
}

#pragma mark - Public

- (void)toggleNavigationBarAndStatusBarVisibility
{
    BOOL willShow = self.navigationController.navigationBarHidden;

    if (willShow) {
        [self toggleStatusBarHiddenWithAppearanceUpdate:NO];
        [self toggleNavigationBarHiddenAnimated:YES];
    } else {
        [self toggleNavigationBarHiddenAnimated:YES];
        [self toggleStatusBarHiddenWithAppearanceUpdate:YES];
    }
}

#pragma mark - Private

- (void)toggleStatusBarHiddenWithAppearanceUpdate:(BOOL)updateAppearance
{
    self.statusBarHidden = !self.isStatusBarHidden;

    if (updateAppearance) {
        [UIView animateWithDuration:UINavigationControllerHideShowBarDuration animations:^{
            [self setNeedsStatusBarAppearanceUpdate];
        }];
    }
}

- (void)toggleNavigationBarHiddenAnimated:(BOOL)animated
{
    [self.navigationController
     setNavigationBarHidden:!self.navigationController.navigationBarHidden
     animated:animated];
}

@end

And here it is in action. We can also change the default status bar animation by implementing preferredStatusBarUpdateAnimation.