iosiphoneuinavigationcontrollerios11uirefreshcontrol

UIRefreshControl not showing in landscape when in a navigation controller with large titles


I have a plain UITableViewController embedded in a UINavigationController which prefers large titles. I added a refresh control to my table view controller.

On iPhone in iOS 11, if I launch my app in portrait mode, switch to landscape and begin refreshing the table view, the refresh control does not show up. The refresh happens, but the control is just not present. It's not even in the view hierarchy:

view hierarchy

Note that the same does work on iPhone if I'm in portrait mode, and also on iPad in every orientation. It also works on iOS 10 with every device and every orientation and also works on iOS 11 if I disable large titles, so it obviously has something to do with the large titles.

Here is a screenshot from the same thing on iOS 10:

screenshot of the refresh control on iOS 10

Here is the whole setup in Interface Builder:

screenshot of setup

The same thing happens when I try it with a simple UIViewController with an embedded UITableView or UIScrollView.

I'm pretty sure this is a bug. How can I make the refresh control visible on iPhone in landscape?


Solution

  • We fixed this by recreating the refresh control on every rotation. It's called in viewDidLoad() too.

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
    
        if traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass {
            tableView.refreshControl = UIRefreshControl() // !!!
            tableView.refreshControl.addTarget(self, action: #selector(didPullToRefresh), for: .valueChanged)
        }
    }
    
    @objc func didPullToRefresh() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
            tableView.refreshControl.endRefreshing()
        }
        // ...
    }