Status bar and navigation bar appear over my view's bounds in iOS 7
Solution 1:
You can achieve this by implementing a new property called edgesForExtendedLayout
in iOS7 SDK. Please add the following code to achieve this,
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
You need to add the above in your -(void)viewDidLoad
method.
iOS 7 brings several changes to how you layout and customize the appearance of your UI. The changes in view-controller layout, tint color, and font affect all the UIKit objects in your app. In addition, enhancements to gesture recognizer APIs give you finer grained control over gesture interactions.
Using View Controllers
In iOS 7, view controllers use full-screen layout. At the same time, iOS 7 gives you more granular control over the way a view controller lays out its views. In particular, the concept of full-screen layout has been refined to let a view controller specify the layout of each edge of its view.
The
wantsFullScreenLayout
view controller property is deprecated in iOS 7. If you currently specifywantsFullScreenLayout = NO
, the view controller may display its content at an unexpected screen location when it runs in iOS 7.To adjust how a view controller lays out its views,
UIViewController
provides the following properties:
- edgesForExtendedLayout
The
edgesForExtendedLayout
property uses theUIRectEdge
type, which specifies each of a rectangle’s four edges, in addition to specifying none and all. UseedgesForExtendedLayout
to specify which edges of a view should be extended, regardless of bar translucency. By default, the value of this property isUIRectEdgeAll
.
- extendedLayoutIncludesOpaqueBars
If your design uses opaque bars, refine
edgesForExtendedLayout
by also setting theextendedLayoutIncludesOpaqueBars
property to NO. (The default value ofextendedLayoutIncludesOpaqueBars
is NO.)
- automaticallyAdjustsScrollViewInsets
If you don’t want a scroll view’s content insets to be automatically adjusted, set
automaticallyAdjustsScrollViewInsets
to NO. (The default value ofautomaticallyAdjustsScrollViewInsets
is YES.)
- topLayoutGuide, bottomLayoutGuide
The
topLayoutGuide
andbottomLayoutGuide
properties indicate the location of the top or bottom bar edges in a view controller’s view. If bars should overlap the top or bottom of a view, you can use Interface Builder to position the view relative to the bar by creating constraints to the bottom oftopLayoutGuide
or to the top of bottomLayoutGuide. (If no bars should overlap the view, the bottom oftopLayoutGuide
is the same as the top of the view and the top ofbottomLayoutGuide
is the same as the bottom of the view.) Both properties are lazily created when requested.
Please refer, apple doc
Solution 2:
You don't have to calculate how far to shift everything down, there's a build in property for this. In Interface Builder, highlight your view controller, and then navigate to the attributes inspector. Here you'll see some check boxes next to the words "Extend Edges". As you can see, in the first screenshot, the default selection is for content to appear under top and bottom bars, but not under opaque bars, which is why setting the bar style to not translucent worked for you.
As you can somewhat see in the first screenshot, there are two UI elements hiding below the navigation bar. (I've enabled wireframes in IB to illustrate this) These elements, a UIButton and a UISegmentedControl both have their "y" origin set to zero, and the view controller is set to allow content below the top bar.
This second screenshot shows what happens when you deselect the "Under Top Bars" check box. As you can see, the view controllers view has been shifted down appropriately for its y origin to be right underneath the navigation bar.
This can also be accomplished programmatically through the usage of -[UIViewController edgesForExtendedLayout]
. Here's a link to the class reference for edgeForExtendedLayout, and for UIRectEdge
[self setEdgesForExtendedLayout:UIRectEdgeNone];
Solution 3:
I created my view programmatically and this ended up working for me:
- (void) viewDidLayoutSubviews {
// only works for iOS 7+
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
CGRect viewBounds = self.view.bounds;
CGFloat topBarOffset = self.topLayoutGuide.length;
// snaps the view under the status bar (iOS 6 style)
viewBounds.origin.y = topBarOffset * -1;
// shrink the bounds of your view to compensate for the offset
viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
self.view.bounds = viewBounds;
}
}
Source (in topLayoutGuide section at bottom of pg.39).
Solution 4:
Swift 3 / Swift 4 solution that also works with NIBs/XIB files in iOS 10+:
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = []
}