21
votes

Under iOS 13, if you setup a scrollable root view controller (such as a UITableViewController) in a navigation controller and then put that navigation controller in the detail pane of a UISplitViewController, then the nav bar's background isn't visible when the scrollable content is at the top.

You can see this by creating a new iOS project based on the Master/Detail template. Then modify the storyboard to use a UITableViewController inside the detail pane's nav controller. Put the device/simulator in Light Appearance mode (it shows the problem better than Dark mode). Run the app and notice the nav bar area is the same color as the table view background. Now scroll the table view up and the nav bar color changes to the standard light gray. Let the table view return to the top and the nav bar color disappears again.

I've only seen this in the detail pane of a split view controller.

How do you turn off this "feature" so that the nav bar looks normal just like every other nav bar used anywhere else other than the detail pane of a split view controller?

There are no relevant API changes for UISplitViewController or UISplitViewControllerDelegate. There's nothing in UINavigationController either.

After some digging I found one workaround but I'd love to find a way to avoid having to do this.

The UINavigationBar class now has some new properties for setting its appearance. Oddly, none of these are mentioned under the "Customizing the Appearance of a Navigation Bar" in the documentation for UINavigationBar.

There are three new properties in iOS 13:

  • standardAppearance
  • compactAppearance
  • scrollEdgeAppearance

All three are of type UINavigationBarAppearance.

Only the first one is set by default.

Even though scrollEdgeAppearance is nil, the detail pane of a split controller acts as if this has been set with the backgroundColor set to the clear color.

So the workaround is to add the following line to the viewDidLoad method of the navigation controller's root view controller:

navigationController?.navigationBar.scrollEdgeAppearance = navigationController?.navigationBar.standardAppearance

Why is this needed only in this one case? Is there a more correct solution other than adding this code?

I noticed that none of Apple's apps (Mail, Notes, and Files at least) seem to use this "feature".

1
Can't figure out if this is related to my independent discussion here stackoverflow.com/a/56941896/341994 If it is, I should delete that answer and refer to this, perhaps... See what you think.matt
@matt This question is specific to how the nav bar appears in the detail pane of a split view. This question is not related to large titles or the status bar. Both issues may be solved setting scrollEdgeAppearance but the questions are too different.rmaddy
OK thanks, that's what I wasn't clear on.matt

1 Answers

10
votes

The workaround you found is the 'official' way to disable this behavior, as explained in a thread on Twitter by David Duncan who is on the iOS System Experience team at Apple.

to control what happens when the UINavigationBar is completely unfurled, you want to set the scrollEdgeAppearance. By setting standardAppearance and scrollEdgeAppearance to the same values, you will get a bar that doesn't change.

An Apple app that does not disable this behavior is the Settings app.