15

I'm trying to use the standard UIRefreshControl and UISearchController on a UITableViewController. However it doesn't look like it does what it's supposed to. When refreshing, scrolling leaves the navigation bar with a big blank area, presumably where the spinner is supposed to be:

enter image description here

I have a sample project on GitHub. Here's how the controls are set up:

override func viewDidLoad() {
    super.viewDidLoad()

    let spinner = UIRefreshControl()
    spinner.addTarget(self, action: #selector(refresh), for: .valueChanged)
    refreshControl = spinner

    searchController = UISearchController(searchResultsController: nil)
    navigationItem.searchController = searchController
}

I've tried assigning the refresh control to the property on UITableView instead of the one on UITableViewController, that doesn't make a difference.

Has anyone come across the same issue?

Allen Zeng
  • 2,635
  • 2
  • 20
  • 31
  • I'm seeing this issue too. It works correctly for me if I remove the search bar or if I add the search bar as the table view's header instead of setting it to the navigationItem. Looks like a bug when the navbar tries to handle both. – McCygnus Oct 26 '17 at 17:47
  • I have this problem too. Unless I remove the searchbar by "self.navigationItem.searchController = nil" I get a crash. – Bassebus Nov 21 '17 at 15:48
  • 6
    I got in touch with Apple, they have confirmed that it's a bug. – Allen Zeng Nov 23 '17 at 00:40

2 Answers2

10

You can use UIRefreshController in the old way, which is like this:

override func viewDidLoad() {
    super.viewDidLoad()

    let spinner = UIRefreshControl()
    spinner.addTarget(self, action: #selector(refresh), for: .valueChanged)
    self.tableView.addSubview(spinner)

    searchController = UISearchController(searchResultsController: nil)
    navigationItem.searchController = searchController
}
0

Just recreate and assign the refresh control every time the table view controller appears on screen.

If you subclassed UITableViewController:

class MyTableViewController: UITableViewController {

    ...

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        refreshControl = UIRefreshControl(...)
    }
}

If you use view controller containment:

class MyContainerViewController: UITableViewController {

    private let tableViewController = UITableViewController(style: .plain)

    ...

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tableViewController.refreshControl = UIRefreshControl(...)
    }
}
lucamegh
  • 527
  • 6
  • 16