21

I'm seeing when I migrated my app to iOS 7, the nav bar is appearing under the status bar when presenting a view controller. I think a lot of people have run into this same issue. Here's a screenshot of what I'm seeing:

existing nav

Requirements:

  • The new view must appear "modally", i.e. I need presentViewController.

  • Display some sort of nav bar or toolbar, with the status bar taking on the background color of the nav bar ala iOS 7 style.

  • It must work on iOS 6.

  • I'm using a xib to handle layout, with autolayout enabled.

Options:

A. Shift your view's frame down by a bit.

Ugh, are we back to the pre-iOS 5 days and mucking with frames? Also it's generally not a good idea mixing with autolayout.

B. Add a little gap up top below your nav bar.

One disadvantage of options A and B is the status bar won't blend into your nav:

nav with gap

C. Programatically add constraints.

The main disadvantage is you'll have to muck with constraints and calculating the nav and status bar heights. Yuck.

D. Stretch the navigation bar / toolbar's height to include the area of the status bar.

Looks good on iOS 7, but breaks on iOS 6. You'll need to programatically update the height of the nav bar, and also make sure the rest of your view updates appropriately. Messy.

enter image description here

E. Mess with iOS6/7 deltas in IB.

Multiple disadvantages: You'll be hardcoding the ios6/7 deltas. Also doesn't work with autolayout.

F. Use a nested UINavigationController.

This is the workaround I selected. See answer below.

uinavcontroller workaround

bobics
  • 2,301
  • 2
  • 23
  • 25
  • I have to same problem, cannot find a clean way to migrate my app quickly and not too dirtily. I hate that Apple says "We have decided that you should rewrite your whole app, please do so." – Thibault D. Sep 27 '13 at 13:49

4 Answers4

29

The easiest workaround I've found is to wrap the view controller you want to present inside a navigation controller, and then present that navigation controller.

MyViewController *vc = [MyViewController new];
UINavigationController *nav = [[UINavigationController alloc] 
    initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:NULL];

Advantages:

  • No mucking with frames needed.
  • Same code works on iOS 6 an iOS 7.
  • Less ugly than the other workarounds.

Disadvantages:

  • You'll probably want to leave your XIB empty of navigation bars or toolbars, and programatically add UIBarButtonItems to the navigation bar. Fortunately this is pretty easy.
bobics
  • 2,301
  • 2
  • 23
  • 25
  • Best solution for me so far. – Maksim Oct 21 '13 at 12:08
  • Another advantage of using this method vs setting a constraint to the top layout guide is that if you change the tint colour of the navigation bar, the colour will extend under the status bar. With the constraint method the background of the view will be under the status bar. – emp Dec 09 '13 at 21:29
  • The problem is there using this method. I'm using [self dismissViewControllerAnimated:YES completion:nil]; for hide it maybe that's the problem – returnvoid Mar 31 '14 at 21:48
  • I have been searching for a solution to this problem quite some time. In my opinion this is the easiest of all. And you can use the navigation bar as some kind of dialog title. Thanks for posting this. – henrik Jul 07 '14 at 18:18
  • @henrik glad you found it useful. I spent quite a bit of time trying to figure out the best / easiest solution, and posted the question + answer pair in hopes it would save time for others – bobics Jul 07 '14 at 19:37
8

You need to add a Vertical Constraint from your top most view to Top Layout Guide as described in the following article by Apple.

https://developer.apple.com/library/ios/qa/qa1797/_index.html

enter image description here

Yas Tabasam
  • 10,517
  • 9
  • 48
  • 53
  • Note the Apple article only describes a method with storyboards in IB, but not with xibs (in IB or programatically) as described in the original question. My app is relatively complex and has a mix storyboards (for simpler collections of related views) and xibs. This is a good solution for storyboards, and it's a technique I'm already using. Programatically adding constraints, while it's something I do when needed, can turn into a can of worms. Also since topLayoutGuide iOS 7 only (iOS 6 is a requirement in the question), you'll also need conditional code for this. – bobics Sep 26 '13 at 08:53
3

Next code worked for me. Just put it to the controller which is presenting the new controller.

#pragma mark hidden status bar
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
}
Jwlyan
  • 84
  • 1
  • 3
0

open you xib file and select the viewcontroller. in the inspector tab select the attributes and select in TopBar "Opaque Navigation Bar". this solved the problem for me.

thorb65
  • 2,696
  • 2
  • 27
  • 37