iosswiftuikituisearchcontrollerpreferslargetitles

UISearchController with Large titles, UI misbehave on dismissing


I have a UITableViewController which has a UISearchController in the navigation bar.

When I tap the search, pull down once and then press cancel, I see a weird UI behavior.

Search Controller

I can't find any particular reasons why this happens. This issue is not reproduced every time. It happens more often when the navigation bar has some buttons, as you can see in the GIF above.

When I go back to the first view controller (which does not have any navigation bar buttons) and repeat same steps, the issue is reproduced on rare occasions.

This issue happens only when you pull down in the ViewController which has the search controller. If you are using a results controller and pull down in the results controller, this issue is not reproduced.

Below is the code used in the sample app.

import UIKit

class SearchViewController: UITableViewController {

    lazy var resultsController = ResultsVC()
    lazy var searchController = UISearchController(searchResultsController: resultsController)

    override func viewDidLoad() {
        super.viewDidLoad()

        configureSearchController()

        navigationItem.largeTitleDisplayMode = .always
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationItem.title = "Search VC"
    }

    func configureSearchController() {
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = true
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.hidesNavigationBarDuringPresentation = true
        searchController.searchResultsUpdater = resultsController
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        navigationController?.pushViewController(SearchViewController(), animated: true)
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 50
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "Searchable cell"
        return cell
    }
}

class ResultsVC: UITableViewController {

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 50
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "Result cell"
        return cell
    }
}

extension ResultsVC: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        print(searchController.searchBar.text)
    }
}

I tried to change the tableView's content offset using tableView.setContentOffet in UISearchControllerDelegate methods willPresentSearchController and willDismissSearchController but the y position varies for each device, and it cannot be a universal fix.

PS: This issue doesn't occur in most simulators. So kindly try the same code in your mobile.


Solution

  • This issue can be prevented from happening by setting

    searchController.obscuresBackgroundDuringPresentation = true

    This means that user can not scroll the table view after tapping search. However, the user can scroll the results controller after it is presented.