2

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

Kenny Wyland
  • 20,844
  • 26
  • 117
  • 229
  • "I also noticed the difference that the section headers in the code version are taller, with bold text in upper+lower case, but are shorter, non-bold, and all upper case in the storyboard version." Right, well that's because your Code is creating this as a Plain table view but your storyboard is creating it as a Grouped table view. – matt Jan 23 '22 at 21:28
  • Also don't forget that iOS 15 adds header padding. If you don't want that, you have to say `self.tableView.sectionHeaderTopPadding = 0;` – matt Jan 23 '22 at 21:29
  • @matt Ah yes, I forgot to set the style in my code. I've updated my code to `[[TestTableViewController alloc] initWithStyle:UITableViewStyleGrouped];` – Kenny Wyland Jan 23 '22 at 21:30
  • @matt I've updated the code snippets and the screenshot so they are both using grouped. I've also been using different colors in different parts of the code so that I know which piece of code is the one that is actually affecting what I'm seeing. – Kenny Wyland Jan 23 '22 at 21:36
  • Right, so now for your storyboard example you just need to add the header padding back in. – matt Jan 23 '22 at 21:52
  • @matt I've never seen or heard of the section header padding. A quick google says this is an iOS 15 addition. I do want it, I'm not removing the header padding at all, so that shouldn't be the reason for the content being stuck under the nav bar. :/ – Kenny Wyland Jan 23 '22 at 22:22

2 Answers2

2

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;
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Absolutely wild. Setting the storyboard tableview section header and footer estimate to 0, instead of Automatic, made it work as expected. That's ludicrous and scares the crap out of me because I have no idea why that should work and what is going to blow up when we hit iOS 16 or something. But thank you very much for your investigation on this and your suggestions! – Kenny Wyland Jan 23 '22 at 22:24
  • I guess, sort of. I mean the content is still stuck under the nav bar though... it's just that the header height on that first row pushes the content of the header down far enough that it isn't covered by the nav bar. So, it's a hack that avoids this particular content from being covered, but the content of the table is still being covered by the nav bar. :( So, if I had a first section header that had a different type of content in it, it might still get covered up. Blerg. – Kenny Wyland Jan 23 '22 at 22:32
  • I don't know about that. Can you post the code for the all code version of the example? – matt Jan 24 '22 at 00:18
0

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

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • Interesting that we both focused on the same thing but took it in opposite directions! – matt Jan 27 '22 at 13:02
  • @matt - yeah... I had been fussing around with this prior to seeing your answer. Another post had me looking at differences between what we see in IB vs Code, and how at run-time things don't always seem to show up as expected - specifically related to default values for Content Insets on buttons... which led me down this path. – DonMag Jan 27 '22 at 13:38
  • Yes, I wish the OP would post the working all-code example, as I asked, so we can see what the various height values are in that case. – matt Jan 27 '22 at 14:20
  • @matt - I put up a GitHub repo (link in my answer) with his original code plus my Storyboard version and my Code-Only version... helped me inspect the differences. – DonMag Jan 27 '22 at 14:25