Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why content insets of a UITableView inside a UIPageViewController get messy right after an interaction?

I've created a Page-Based Application and hacked it a bit for some experiments; my simple aim is to have a UIPageViewController whose pages will contain a UIViewController holding a UITableView (after further inspection, the outcome of my experiment is the same if I use a UITableViewController instead). To do this I've simply edited the project template, and added the UIPageViewController as an embedded view of the RootViewController using Storyboard's ContainerView object, as you can see in this screenshot:

storyboard's controllers

Every controller is configured via storyboard to automatically adjust scroll view's content inset, and if I start the project with this configuration everything looks fine, and the DataViewController's tableview has its content insets properly adjusted right under the navigation bar as expected; however, as the user makes an interaction with the tableview, the content insets break and the tableview underlaps the navigation bar:

content inset issue with uipageviewcontroller and a tableview

I have been able to fix this by manually setting the content insets in DataViewController's viewDidLayoutSubview method, and by disabling Adjusts Scroll View Insets on any controller, so I don't need this as an answer to solve my problem. My question is why the content insets are properly set right after the first controller gets loaded from the storyboard the first time, and why they break after any kind of user interaction.

If you need to test it directly, here's a link to the project

like image 910
dev_mush Avatar asked Sep 08 '14 15:09

dev_mush


2 Answers

I'm not 100% sure it's what you're running into, but here's some explanation regarding your setup:

By default, UIViewControllers tend to be configured to extend their content behind non-opaque bars, and to adjust scroll view insets. In your setup above this means that the container VC:

  • Extends its content so as to appear behind the navigation bar
  • Sets its scrollview's .contentInset and .scrollIndicatorInsets to be the same height as the navigation bar

"But, ah!" I hear you say, "that container view controller doesn't have a scroll view". Well this is the tricky bit:

It seems UIViewController's definition of "my scroll view" is rather simplistically, "the first scroll view I come to when searching down through my view hierarchy".

UIPageViewController happens to be implemented using a scroll view. So the container VC finds that scroll view, and adjusts its top insets. This is not really what you want; it confuses the page controller, and tends to upset layout at some point.

The simple solution there is simply to turn off .automaticallyAdjustsScrollViewInsets for the container view controller.

You then need to solve the next problem of your table view needing some kind of top insets to account for the navigation bar. So far it seems to me the best way to do this is manually either in the storyboard, or code.

like image 142
Mike Abdullah Avatar answered Nov 15 '22 19:11

Mike Abdullah


Found an elegant solution:

  1. From your storyboard, select your UIPageViewController
  2. In the Attributes inspector, uncheck the option ViewController => Extend Edges => Under Top Bars
  3. That's all, no weird UI hacks
like image 44
javorosas Avatar answered Nov 15 '22 20:11

javorosas