'UITableView content stuck under UINavigationBar, maybe caused by scrollEdgeAppearance?

I've made hundreds of table view controllers over the last decade and I don't know why this is happening. The content of my UITableView is stuck under my UINavigationBar (with a background color) in my UINavigationController. I was having this problem in an existing project, but to try to figure out the problem I created a fresh new project with nothing else in it.

  • I created a project.
  • Created TestTableViewController class that just adds some example sections/rows.
  • Removed the initial view controller from the storyboard.
  • Added a UITableViewController and set its class type to be TestTableViewController.
  • set UITableView's background color to UIColor.systemGroupedBackgroundColor.
  • Change the UITableViewCell to be Basic type and set its cell reuse id to be "Cell".
  • Told the storyboard to embed the TestTableViewController in a UINavigationController.
  • Set that UINavigationController as the Initial View Controller.

When I start the app, the navigation bar is hidden (I believe due to the scrollEdgeAppearance) and when I start to scroll away from the top edge, the nav bar starts to show up.

But I need a background color on my nav bar, so:

  • In the storyboard, I changed the UINavigationController's nav bar to have a background color.

Now the UITableView content is stuck under the nav bar.

I tried configuring the appearance of the UINavBar in my app delegate:

// in AppDelegate -didFinishLaunchingWithOptions
if (@available(iOS 15.0, *)) {
    UINavigationBarAppearance *appearance = [UINavigationBarAppearance new];
    [appearance configureWithOpaqueBackground];
    appearance.backgroundColor = [UIColor systemRedColor];
    
    UINavigationBar.appearance.standardAppearance = appearance;
    UINavigationBar.appearance.compactAppearance = appearance;
    UINavigationBar.appearance.scrollEdgeAppearance = appearance;
    UINavigationBar.appearance.compactScrollEdgeAppearance = appearance;
    
}

But that didn't change anything. Next:

  • I tried creating a subclass of UINavigationController called TestNavController
  • Updated the storyboard to set the class on the nav to be TestNavController
  • Adding code to -awakeFromNib and -viewDidLoad to explicitly set the style on the nav bar:
// TestNavController, -awakeFromNib
if (@available(iOS 15.0, *)) {
    UINavigationBarAppearance *appearance = [UINavigationBarAppearance new];
    [appearance configureWithOpaqueBackground];
    appearance.backgroundColor = [UIColor systemBlueColor];
    
    self.navigationBar.standardAppearance = appearance;
    self.navigationBar.compactAppearance = appearance;
    self.navigationBar.scrollEdgeAppearance = appearance;
    self.navigationBar.compactScrollEdgeAppearance = appearance;
}

The content is still stuck under the nav bar. Next I tried to take the storyboard out of the equation and in SceneDelegate.m in -scene:willConnectToSession:options, I swapped out the storyboard created root view controller with an entirely code-based root view controller:

TestTableViewController *testvc = [[TestTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
testvc.view.backgroundColor = UIColor.systemGroupedBackgroundColor;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:testvc];
self.window.rootViewController = nav;

and it works exactly as expected! So, why are my storyboard configured viewcontrollers and code-base appearance settings showing the wrong thing, while the code-based viewcontrollers look as expected? I've been using different colors in the various locations so that I can tell which code is the one having the effect. Red is being set in the App Delegate, Blue is being set in the TestTableViewController's awakeFromNib on the navigationItem.

side by side screenshots of the storyboard version and the code version

I thought this was a problem with the scrollEdgeAppearance, but I've tried setting it via code and nothing seems to work.

Why is my content stuck under the nav bar when I use the storyboard? What am I missing?

Here is a link to download the project: https://inadaydevelopment.com/stackoverflow/wtf.zip



Solution 1:[1]

It's a little hard to say whether this is a bug in the storyboard or not; it might be, and you should probably wrap this up into a nicer example and send it to Apple with a bug report. You should provide two projects, one that does everything in code and the other that does as much as possible in the storyboard.

One thing I can tell you is that I don't see Apple using the Grouped style of table with a section zero header. (Settings app is good place to look.) If you suppress your section zero header by setting the title to nil, things look fine because there is no title text getting stuck under the navigation bar.

If you're going to give the zero section a title when using a grouped style, you're probably going to want to compensate by giving the table section header some padding. That will keep it out from underneath the navigation bar. However, I ended up with zero padding after making some other changes.

Another issue I noticed is that it seems to matter what the footer height is. I got a much better look from your storyboard-based project by deliberately setting the footer height to 1 (it wouldn't let me set it to zero). In the end I wound up setting it to 10.

Plus I think you should set the header and footer estimated heights to 0 rather than leaving them at Automatic.

By playing around with all those parameters in my own project, I was able to get this, which looks to me a lot like your code-based example (except that I made the cells yellow so as to see clearly where they are):

enter image description here

Here are the size settings I ended up with (but you should tweak them more until you're happy):

enter image description here

And that's with

self.tableView.sectionHeaderTopPadding = 0;

Solution 2:[2]

This may help...

I took a look at your project and made one change.

Your table view in Storyboard has these settings:

enter image description here

and when I run the app I get this:

enter image description here

Changing only the Sections Header Height and Footer Heights to Automatic:

enter image description here

and I get this:

enter image description here

I created two projects from scratch - one loading the controllers from a Storyboard and one loading via code only - and wrapped everything up into a GitHub repo here: https://github.com/DonMag/wtfTable

Running either wtfSB or wtfNoSB gives me almost identical results (except for the default table background color and slight difference in section header heights):

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 DonMag