Search code examples
iosuinavigationbaruisearchbaruinavigationitemuisearchcontroller

UISearchController expands off screen when tapped


We're having a weird issue with using a UISearchController as an item in a navigation bar. It's set as the left bar button item and when a user taps to start searching, the search bar expands to the right off the side of the screen.

Below is the code for creating the UISearchController:

resultSearchController = ({
    let controller = UISearchController(searchResultsController: nil)
    controller.searchResultsUpdater = self
    controller.dimsBackgroundDuringPresentation = false
    controller.hidesNavigationBarDuringPresentation = false
    controller.searchBar.delegate = self
    controller.delegate = self

    controller.searchBar.frame = CGRect(x: 0, y: 0, width: 266, height: 44.0)
    let searchBarView = UIView(frame: controller.searchBar.frame)
    searchBarView.addSubview(controller.searchBar)

    controller.searchBar.backgroundImage = UIImage(named: "searchBarBG")
    controller.searchBar.barTintColor = .white
    controller.searchBar.subviews[0].subviews.flatMap(){ $0 as? UITextField }.first?.tintColor = Constants.Colors.Red

    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: searchBarView)

    return controller
})()

When the screen first loads, it looks like this.

After tapping on the search bar, it changes to look like this.

I have no idea what's causing this. After lots of searching, I tried changing self.definesPresentationContext = false; and self.extendedLayoutIncludesOpaqueBars = true as well as adjusting similar checkboxes in the storyboard. Any tips?

Edit: This only seems to happen on iOS 11. In 10.3, the search bar actually shrinks a little to accommodate the Cancel button but ultimately takes up the same amount of space.


Solution

  • I ended up fixing this by overriding the didPresentSearchController and didDismissSearchController methods as part of the UISearchControllerDelegate.

    extension ContactUsViewController: UISearchControllerDelegate {
    
        func didPresentSearchController(_ searchController: UISearchController) 
        {
            searchController.searchBar.frame = CGRect(x: 0, y: 0, width: 266, height: 44.0)
        }
    
        func didDismissSearchController(_ searchController: UISearchController) 
        {
            searchController.searchBar.frame = CGRect(x: 0, y: 0, width: 266, height: 44.0)
        }
    }