109

I have a ViewController which is inside a UINavigationcontroller, but the navigationBar is hidden. When I run the app on iOS 7, the status bar shows on top of my view. Is there a way to avoid this?

I don't want to write any OS specific code.

Enter image description here

I tried setting View controller-based status bar appearance to NO, but it did not fix the issue.

Bhavin Ramani
  • 3,221
  • 5
  • 30
  • 41
aryaxt
  • 76,198
  • 92
  • 293
  • 442
  • 2
    You need to adjust y origin and delta value as well to handle the status bar issue This may helps you http://stackoverflow.com/q/18980925/1545180 – Ganapathy Oct 02 '13 at 13:33
  • I have posted my answer to show status bar like iOS 6 in iOS 7 http://stackoverflow.com/questions/18294872/ios-7-status-bar-back-to-ios-6-style/19044681#19044681 – Desert Rose Sep 27 '13 at 07:12

14 Answers14

95

Xcode 5 has iOS 6/7 Deltas which is specifically made to resolve this issue. In the storyboard, I moved my views 20 pixels down to look right on iOS 7 and in order to make it iOS 6 compatible, I changed Delta y to -20.

enter image description here

Since my storyboard is not using auto-layout, in order to resize the height of views properly on iOS 6 I had to set Delta height as well as Delta Y.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
aryaxt
  • 76,198
  • 92
  • 293
  • 442
  • 8
    your answer is right but doesn't work with 4" display. Please update your answer if you can make it work for 4" display as well. Thanks in advance. –  Sep 17 '13 at 07:27
  • 2
    @AnkitMehta I didn't have to do anything specific for 4" iphones – aryaxt Sep 17 '13 at 22:44
  • 5
    worked for me. Notice that in order to see this deltas, you have to deselect 'Use Autolayout' under 'Identity and Type' for storyboard. – marsant Oct 03 '13 at 22:12
  • genius! thanks!!! when I reload my view continously, the height of the view keeps shrinking. I have no code in my implementation file that is modifying the frame in any way. Is there something that the deltaY might be doing? – kevinl Oct 28 '13 at 16:37
  • 2
    I found out besides setting a -20 for ∆Y, I had to also set a +20 to ∆Height – Toland Hon Nov 06 '13 at 19:16
  • I'm using XCode 5.0.2, and not seeing deltas. Is there something to show/hide them? NOTE: I also don't have the example display you're showing, that area is now where the X, Y, Wid, Hght are. Also note: I *am* using autolayout (inherited project.) – Olie Nov 15 '13 at 23:52
  • @aryaxt "I had to set Delta height as well as Delta Y" you set in code or in XIB ? – onmyway133 Nov 24 '13 at 07:51
  • @entropy I did in story board – aryaxt Nov 24 '13 at 15:07
  • 3
    What happens when statusbar height will change? F.ex.: when user activates hot-spot, etc.... then height is 40px... – Lukasz Jan 10 '14 at 13:05
  • @AnkitMehta,@Idan I'm having the same issue with 4'' display, have you solved it? – laucel Mar 10 '14 at 15:26
  • 1
    @laucel Yes the issue is solved as given in this answer. Did you try the given answer, Please note that the issue is with iOS7 not with 3.5" Or 4". –  Mar 11 '14 at 08:38
  • @Ankit Mehta thanks for the answer. I'm successfully using the given answer on iPad, but on iPhone with iOS6 it isn't working, the y of the view is still 20, delta -20 has not been applied – laucel Mar 11 '14 at 10:08
  • 1
    @laucel, Please check your autosizing part as well this must be changed accordingly. Hope you know how autosizing works. –  Mar 11 '14 at 10:52
68

If you simply do NOT want any status bar at all, you need to update your plist with this data: To do this, in the plist, add those 2 settings:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

In iOS 7 you are expected to design your app with an overlaid transparent status bar in mind. See the new iOS 7 Weather app for example.

Nathan H
  • 48,033
  • 60
  • 165
  • 247
  • 3
    This is actually the only good answer since it fixes the issue at its core in the way it was meant to be done. So: upvotes needed! – eleven59 Oct 04 '13 at 16:03
  • 5
    It might be appropriate for some situations, but you want to be very careful hiding the status bar. Only for views that are justifiably full screen, like media players or image viewers. – SmileBot Oct 08 '13 at 03:03
  • 1
    @eleven59, you mean the way the autocrats at Apple intend. – JohnK Oct 09 '13 at 14:05
  • 1
    Definitely like this better than changing the offset of a view controller (which feels really dirty). – Benjamin Oman Oct 09 '13 at 17:34
  • hiding status bar is not a good idea... I know this is easiest way to handle iOS 7, but timing is NEEDED... – Fahim Parkar Oct 20 '13 at 09:34
  • @FahimParkar I agree, however it was my understanding that the user asked for something like. In some apps it makes sense, in others not so much. – Nathan H Oct 20 '13 at 09:41
  • What if the client demands the status bar to be shown? How to I fix all my bugs? Just uninstall the app! Not helpful. – 最白目 Jan 15 '14 at 10:17
  • @dan I don't understand your comment. What client? What bugs? What are we talking about? – Nathan H Jan 16 '14 at 11:54
  • I mean you wrote if the status bar covers the view, solve it by removing the status bar right? (seriously, I may be wrong). If I do so but my client/boss/customer wants it to be shown the answer is not helpful. – 最白目 Jan 16 '14 at 12:53
  • @dan My answer was to the specific question, which asked to hide the status bar. You don't have to hide it if you don't want to! If you want to keep the status bar, do *nothing* and make your design match the new iOS 7 appearance. The Apple-way. – Nathan H Feb 19 '14 at 13:11
43

This is the default behaviour for UIViewController on iOS 7. The view will be full-screen which means the status bar will cover the top of your view.

If you have a UIViewController within a UINavigationController and the navigationBar is visible, you can have the following code in your viewDidLoad or have a background image for navigationBar do the trick.

self.edgesForExtendedLayout = UIRectEdgeNone;

If you have navigationBar hidden, then you have to adjust all the UIView elements by shifting 20 points. I dont't see any other solution. Use auto layout will help a little bit.

Here is the sample code for detecting the iOS version, if you want to backward compatibility.

NSUInteger DeviceSystemMajorVersion() {
    static NSUInteger _deviceSystemMajorVersion = -1;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        _deviceSystemMajorVersion = [[systemVersion componentsSeparatedByString:@"."][0] intValue];
    });

   return _deviceSystemMajorVersion;
}
Bhavin Ramani
  • 3,221
  • 5
  • 30
  • 41
Vincent
  • 1,386
  • 9
  • 9
  • 18
    Instead of fetching, parsing and comparing the system version, it is recommended to use `if ([self respondsToSelector:@selector(edgesForExtendedLayout)])` – Sebastian Hojas Oct 07 '13 at 15:14
15

Only working solution i've made by my self.

Here is my UIViewController subclass https://github.com/comonitos/ios7_overlaping

1 Subclass from UIViewController

2 Subclass your window.rootViewController from that class.

3 Voila!

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

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect screen = [[UIScreen mainScreen] bounds];
        if (self.navigationController) {
            CGRect frame = self.navigationController.view.frame;
            frame.origin.y = 20;
            frame.size.height = screen.size.height - 20;
            self.navigationController.view.frame = frame;
        } else {
            if ([self respondsToSelector: @selector(containerView)]) {
                UIView *containerView = (UIView *)[self performSelector: @selector(containerView)];

                CGRect frame = containerView.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                containerView.frame = frame;
            } else {
                CGRect frame = self.view.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                self.view.frame = frame;
            }
        }
    }
}

4 Add this to make your status bar white Just right after the [self.window makeKeyAndVisible]; !!!

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
Tim Kozak
  • 4,026
  • 39
  • 44
  • but this is not showing the time at the top... Biggest disadvantage... :( – Fahim Parkar Oct 20 '13 at 09:29
  • Works great, but for step 4 you should use preferredStatusBarStyle in your view controller, as setStatusBarStyle is deprecated and it's default action is to do nothing. http://stackoverflow.com/a/19014724/1192732 – CpnCrunch Aug 25 '16 at 16:53
13
-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

-(void)viewWillLayoutSubviews{

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
  {
    self.view.clipsToBounds = YES;
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = 0.0;
    if(UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        screenHeight = screenRect.size.height;
    else
        screenHeight = screenRect.size.width;
    CGRect screenFrame = CGRectMake(0, 20, self.view.frame.size.width,screenHeight-20);
    CGRect viewFrame1 = [self.view convertRect:self.view.frame toView:nil];
    if (!CGRectEqualToRect(screenFrame, viewFrame1))
    {
        self.view.frame = screenFrame;
        self.view.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    }
  }
}

Add Key in plist--- View controller-based status bar appearance : NO

Darshit Shah
  • 2,366
  • 26
  • 33
  • change window color if require – Darshit Shah Dec 24 '13 at 10:19
  • Thanks, It solved my overlapping issue. But one issue still there - View controller-based status bar appearance : NO is to hide status bar I guess. But when I set it to YES, then its not showing status bar and when I set it to NO then it's showing status bar. So plz tell me am I wrong with concept or what? – Nayan Jan 23 '14 at 06:15
  • 1
    I think because take default semi transparant color set in didFinishLaunchingWithOptions 'self.window.backgroundColor = [UIColor blueColor];' and set in plist View controller-based status bar appearance YES – Darshit Shah Jan 23 '14 at 10:02
  • Nice thanks! Also, just to point out that apple docs recommend if checking with if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) {} else {}. Cheers! – Joel Balmer Feb 14 '14 at 17:13
  • Thank you so much.Your code is so helpful for us.Please need to explain about viewWillLayoutSubviews function. – user3182143 Feb 23 '16 at 12:53
4

To hide status bar in ios7 follow these simple steps :

In Xcode goto "Resources" folder and open "(app name)-Info.plist file".

  • check for "View controller based status bar appearance" key and set its value "NO"
  • check for "Status bar is initially hidden" key and set its value "YES"

If the keys are not there then you can add it by selecting "information property list" at top and click + icon

Mandeep Pasbola
  • 2,631
  • 2
  • 26
  • 50
3

If you wan to hide it completely and just avoid dealing with it, this works well.

-(BOOL) prefersStatusBarHidden
{
    return YES;
}

reference https://stackoverflow.com/a/18873777/1030449

Community
  • 1
  • 1
Kalel Wade
  • 7,742
  • 3
  • 39
  • 55
3

If using xibs, a very easy implementation is to encapsulate all subviews inside a container view with resizing flags (which you'll already be using for 3.5" and 4" compatibility) so that the view hierarchy looks something like this

xib heirarchy

and then in viewDidLoad, do something like this:

- (void)viewDidLoad
{
  [super viewDidLoad];
  // initializations
  if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) // only for iOS 7 and above
  {
    CGRect frame = containerView.frame;
    frame.origin.y += 20;
    frame.size.height -= 20;
    containerView.frame = frame;
  }
}

This way, the nibs need not be modified for iOS 7 compatibility. If you have a background, it can be kept outside containerView and let it cover the whole screen.

tipycalFlow
  • 7,594
  • 4
  • 34
  • 45
3

This is all that is needed to remove the status bar. enter image description here

Tony
  • 4,609
  • 2
  • 22
  • 32
2

For Navigation Bar :

Writing this code :

self.navigationController.navigationBar.translucent = NO;

just did the trick for me.

Saru
  • 863
  • 1
  • 15
  • 23
1

I have posted my answer to another post with the same question with this one.

From Apple iOS7 transition Guide, https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/AppearanceCustomization.html#//apple_ref/doc/uid/TP40013174-CH15-SW1

Specifically automaticallyAdjustsScrollViewInsets=YES and set self.edgesForExtendedLayout = UIRectEdgeNone works for me when I don't want to the overlap and I have a tableviewcontroller.

stema
  • 90,351
  • 20
  • 107
  • 135
Liangjun
  • 601
  • 4
  • 13
1

Vincent's answer edgesForExtendedLayout worked for me.

These macros help in determining os version making it easier

// 7.0 and above 
#define IS_DEVICE_RUNNING_IOS_7_AND_ABOVE() ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) 

// 6.0, 6.0.x, 6.1, 6.1.x
#define IS_DEVICE_RUNNING_IOS_6_OR_BELOW() ([[[UIDevice currentDevice] systemVersion] compare:@"6.2" options:NSNumericSearch] != NSOrderedDescending) 

add these macros to prefix.pch file of your project and can be accessed anywhere

if(IS_DEVICE_RUNNING_IOS_7_AND_ABOVE())
{
 //some iOS 7 stuff
 self.edgesForExtendedLayout = UIRectEdgeNone;
}

if(IS_DEVICE_RUNNING_IOS_6_OR_BELOW())
{
 // some old iOS stuff
}
RamaKrishna Chunduri
  • 1,100
  • 1
  • 11
  • 15
0

If you want "Use Autolayout" to be enabled at any cost place the following code in viewdidload.

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
{
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.extendedLayoutIncludesOpaqueBars = NO;
        self.automaticallyAdjustsScrollViewInsets = NO;
}
Ali Shahid
  • 516
  • 1
  • 5
  • 21
0

My status bar and navigation bar overlap after return from landscape view of YTPlayer. Here is my solution after trying @comonitos' version but not work on my iOS 8

- (void)fixNavigationBarPosition {
    if (self.navigationController) {
        CGRect frame = self.navigationController.navigationBar.frame;
        if (frame.origin.y != 20.f) {
            frame.origin.y = 20.f;
            self.navigationController.navigationBar.frame = frame;
        }
    }
}

Just call this function whenever you want to fix the position of navigation bar. I called on YTPlayerViewDelegate's playerView:didChangeToState:

- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state {
    switch (state) {
        case kYTPlayerStatePaused:
        case kYTPlayerStateEnded:
            [self fixNavigationBarPosition];
            break;
        default:
    }
}
John Pang
  • 2,403
  • 25
  • 25