2
votes

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.

2
Does it change if you alter the constants in controller.searchBar.frame?Carlos
It changes the starting size of the search bar, but it still expands out past the side of the screen when tapped.Nick M
Have you checked the constraints on it? Beware of error messages related to the constraints breaking.Carlos
We don't have any constraints on it. It's created programmatically as shown above.Nick M

2 Answers

2
votes

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)
    }
}
1
votes

If you don't need the added functionality of UISearchBarController you can directly use UISearchBar, which has a more predictable resizing behavor:

let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: 200, height: 20))
searchBar.delegate = self
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: searchBar)

Note that if you use the built-in cancel button or other similar features you'll have to manually handle them in the delegate methods.