jcrowson jcrowson - 2 months ago 4x
iOS Question

Hiding status bar after view has loaded leaves black bar

I'm running into a bit of a weird problem when hiding the status bar after the view had loaded. If I add the following method in the ViewDidLoad method, the status bar is completely removed from the view:

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];

However, if I call this method in an IBAction or another method, the status bar still slides away but leaves a black bar the same height as itself behind.

I've thought about shifting the entire view up by 20px but is this really a fix? I don't want to just overlap a black bar incase the status bar height changes in future OS upgrades.

Status bar leaving black bar


Hard-coding any number is always counter to future proofing. Your concerns are correct. There is a bit of a trick to properly handling the hiding of the statusBar. But all the needed information is available.

For example the UIApplication singleton has a property named statusBarFrame which is precisely what it sounds like, a CGRect of the statusBar's frame. The cool thing is that once you have called setStatusBarHidden:withAnimation: that property will give you the new frame, even before the animation completes. So really you are simply left with some basic math to adjust the view's frame.

In short your gut feeling is correct; always compute things live.

I've had good success with a category method like this. (Even when toggling in-call status bar in simulator(Command - T)):

@implementation UIApplication (nj_SmartStatusBar)
// Always designate your custom methods by prefix.
-(void)nj_setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation{
    UIWindow *window = [self.windows objectAtIndex:0];
    UIViewController *rootViewController = window.rootViewController;
    UIView *view = rootViewController.view;

    // slight optimization to avoid unnecassary calls.
    BOOL isHiddenNow = self.statusBarHidden;
    if (hidden == isHiddenNow) return;

    // Hide/Unhide the status bar
    [self setStatusBarHidden:hidden withAnimation:animation];

    // Get statusBar's frame
    CGRect statusBarFrame = self.statusBarFrame;
    // Establish a baseline frame.
    CGRect newViewFrame = window.bounds;

    // Check if statusBar's frame is worth dodging.
    if (!CGRectEqualToRect(statusBarFrame, CGRectZero)){
        UIInterfaceOrientation currentOrientation = rootViewController.interfaceOrientation;
        if (UIInterfaceOrientationIsPortrait(currentOrientation)){
            // If portrait we need to shrink height
            newViewFrame.size.height -= statusBarFrame.size.height;
            if (currentOrientation == UIInterfaceOrientationPortrait){
                // If not upside-down move down the origin.
                newViewFrame.origin.y += statusBarFrame.size.height;
        } else { // Is landscape / Slightly trickier.
            // For portrait we shink width (for status bar on side of window)
            newViewFrame.size.width -= statusBarFrame.size.width;
            if (currentOrientation == UIInterfaceOrientationLandscapeLeft){
                // If the status bar is on the left side of the window we move the origin over.
                newViewFrame.origin.x += statusBarFrame.size.width;
    // Animate... Play with duration later...
    [UIView animateWithDuration:0.35 animations:^{
        view.frame = newViewFrame;