Why does UIViewController extend under UINavigationBar, while UITableViewController doesn't?
Solution 1
By default, UITableViewController's views are automatically inset in iOS7 so that they don't start below the navigation bar/status bar. This is controller by the "Adjust scroll view insets" setting on the Attributes Inspector tab of the UITableViewController in Interface Builder, or by the setAutomaticallyAdjustsScrollViewInsets:
method of UIViewController.
For a UIViewController's contents, if you don't want its view's contents to extend under the top/bottom bars, you can use the Extend Edges Under Top Bars/Under Bottom Bars settings in Interface Builder. This is accessible via the edgesForExtendedLayout
property.
Solution 2
Objective-C:
- (void)viewDidLoad {
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeNone;
}
Swift 2:
self.edgesForExtendedLayout = UIRectEdge.None
Swift 3+:
self.edgesForExtendedLayout = []
Solution 3
@Gank's answer is correct, but the best place to do this is on the UINavigationControllerDelegate
(if you have one):
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
viewController.edgesForExtendedLayout = UIRectEdge.None
}
unspokenblabber
Updated on July 02, 2020Comments
-
unspokenblabber almost 4 years
I have
UITabbarController
withUINavigationController
in it. I have a subclass ofUIView
that I assign as theview
ofUIViewController
in thenavController
. This is pretty standard stuff, right? This is how I do it_productCategoryView = [[ProductCategoryView alloc] initWithFrame:self.view.frame]; self.view = _productCategoryView;
This
view
has aUITableView
assubView
_productCategoryTableView = [[UITableView alloc] initWithFrame:self.frame style:UITableViewStylePlain]; _productCategoryTableView.separatorStyle = UITableViewCellSeparatorStyleNone; _productCategoryTableView.backgroundColor = [UIColor clearColor]; [self addSubview:_productCategoryTableView];
For the sake of debugging I am setting
self.backgroundColor = [UIColor blueColor]
on the view.From the above initialization of
tableView
one might think that the view's and table'sframe
is same. However when I run iniOS 7
, the view's origin is set behind theUINavigationBar
. This is understandable because I am settingself.navigationBar.translucent = YES;
in my subclass ofUINavigationController
. But what I don't understand is how come the table is sitting just below thenavBar
? Shouldn't it also start from(0, 0)
which is behind thenavBar
? See screenshotScenario 1
below. Notice the blue hue behindnavBar
Now, I
push
anotherviewController
on the navigation stack, simply by using[self.navigationController pushViewController.....]
. Again I have a customUIView
with atableView
in it. However I also have aUILabel
above this table, and again for debugging, I gave it aredColor
. This time I am setting the label'sorigin
to be almost same as the view'sCGRect boundsInset = UIEdgeInsetsInsetRect(self.bounds, UIEdgeInsetsMake(10, 10, 10, 10)); CGSize textSize = [_titleLabel.text sizeWithFont:_titleLabel.font constrainedToSize:CGSizeMake(boundsInset.size.width, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping]; printSize(textSize); _titleLabel.frame = CGRectMake(boundsInset.origin.x, boundsInset.origin.y, boundsInset.size.width, textSize.height);
So, going by the logic above, the label should be visible, right? But this time it's not. This time the label is behind the
navBar
.Notice, the red hue behind navBar.
I would really like to align the subView below the navBar consistently. My questions are
1. How is the tableView offset by 64pixels (height of nav + status bar in iOS 7) automatically, even though it's frame is same as the view's?
2. Why does that not happen in the second view?