Search code examples
iosuitableviewuiviewcontrolleruinavigationcontrolleruikit

UIViewController: extendedLayoutIncludesOpaqueBars and scroll view offset


My app's view hierarchy is pretty straightforward: a UINavigationController contains a UITableViewController. The navigation controller's navigation bar is opaque, which causes some strange inset behavior of the table view during navigation transitions, seen here:

Navigation Inset Issue

To remedy this, I'm setting extendedLayoutIncludesOpaqueBars to true on the UITableViewController. Doing so properly extends the view beneath the navigation bar, but changes the behavior of the table view's contentOffset in a way that I don't quite understand. With this property set to true, the Y-value of the table view's contentOffset reports that it is offset higher than it should be by the current height of the navigation bar (i.e. scrolling the table view 1pt, it reports that its y-offset is -63pts).

This made me think that the navigation controller was automatically managing the scroll view's contentInset, like it does for translucent bars. But I couldn't see any evidence that the scroll view had content insets set in scrollViewDidScroll(). Even with automaticallyAdjustsScrollViewInsets set to false on the table view controller, the content offset wasn't right, so it seems it's nothing to do with the insets.

Apple's documentation about extendedLayoutIncludesOpaqueBars doesn't mention any effect on the behavior of a scroll view's content offset. Changing the contentInset of the table view unfortunately doesn't solve this.

I tried changing the table view controller's edgesForExtendedLayout property to force it to extend without affecting the scroll view, but it seems this property is powerless against opaque bars.

Is there some hidden behavior with extendedLayoutIncludesOpaqueBars that borks up a scroll view's content offset? Or could this be a bug?


Solution

  • Have you tried this?

    if #available(iOS 11, *) {
        tableView.contentInsetAdjustmentBehavior = .never
    }