Why the 20px gap at the top of my UIViewController?
The Problem
Consider the following controller hierarchy:
UINavigationControllerUIViewControllerUITableViewController
The presence of the UIViewController is affecting layout. Without it, the UITableViewController takes up the entire bounds of the UINavigationController:

However, if I add a vanilla UIViewController between the UINavigationController and UITableViewController, a 20px gap appears between the top of the UIViewController and the top of the UITableViewController:

Even if I reduce my code down to the simplest possible thing, I still observe this behavior. Consider this app delegate code:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
window = new UIWindow(UIScreen.MainScreen.Bounds);
var tableView = new UITableViewController();
var intermediateView = new UIViewController();
var navigation = new UINavigationController(intermediateView);
navigation.View.BackgroundColor = UIColor.Red;
intermediateView.View.BackgroundColor = UIColor.Green;
tableView.View.BackgroundColor = UIColor.Blue;
intermediateView.AddChildViewController(tableView);
intermediateView.View.AddSubview(tableView.View);
tableView.DidMoveToParentViewController(intermediateView);
window.RootViewController = navigation;
window.MakeKeyAndVisible();
return true;
}
The above still shows a 20px gap between the top of the UIView and the top of the UITableView.
My Understanding of the Problem
I understand that something is erroneously allocating space for a status bar. Using Reveal I can see that the Frame of the UITableViewController has a Y value of 20.
Things I've Tried
Unsuccessful
- Set
WantsFullScreenLayouttotrueon theUIViewController,UITableViewController, and both - Playing with
EdgesForExtendedLayoutandExtendedLayoutIncludesOpaqueBarsfor both theUIViewControllerandUITableViewController - Played with
AutomaticallyAdjustsScrollViewInsetson theUIViewController - Played with
PreservesSuperviewLayoutMarginsin theUITableView - Tried overriding
PrefersStatusBarHiddenand returningtruein both theUIViewControllerandUITableViewController
Successful
Overriding ViewDidLayoutSubviews in my UITableViewController thusly:
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
this.View.Frame = this.View.Superview.Bounds;
}
Things I want to know
- is there a clean(er) way of achieving my goal?
- what is actually responsible for adding the 20px gap? The
UIViewController? TheUITableViewController? - what are the best practices for ensuring my view controllers remain usable in different contexts? Presumably overriding
ViewDidLayoutSubviewscouples my view controller to expectations as to where it will be displayed in the visual tree. If it were to be hosted higher up the controller stack, things would not look right. Is there a way to avoid this coupling and thus increase reusability?