Search code examples
iosswiftuicollectionviewoverlapuisearchcontroller

UISearchController searchbar overlaps CollectionView


When launching UISearchController programatically the UISearchBar overlaps CollectionView below.

I've searched here and there and seems that no one had this kind of problem before.

enter image description here enter image description here

There are some limitations on how i can and cannot do it:

  • cannot use tableview header
  • cannot use collectionview header
  • have to use collectionviewcontroller

Already tried Adjust Scroll View Insets and Extend Edges - no use because its a CollectionViewController

The question is: how to do it the right way, using IBAction? The code for IBAction connected to the magnifying glass is:

@IBAction func showSearchBar(_ sender: UIBarButtonItem) {
    let searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    present(searchController, animated: true, completion: nil)
}

Solution

  • Thanks to @noir_eagle suggestion I've implemented completion block for present(searchController, animated: true, completion: nil) method, so it looks like this:

    present(searchController, animated: true, completion: {
            UIView.animate(withDuration: 0.25, animations: {
                self.collectionView?.contentInset = UIEdgeInsets(top: 64, left: 0, bottom: 0, right: 0)
                self.collectionView?.contentOffset = CGPoint(x: 0, y: -64)
            })
        })
    

    I had to do it in this method because UISearchControllerDelegate method didPresentSearchController(_ searchController: UISearchController) and willPresentSearchController(_ searchController: UISearchController) are never called... Dunno why.

    Next, somehow, method didDismissSearchController(_ searchController: UISearchController) of UISearchControllerDelegate is called right after dismissing UISearchBar with Cancel button, so I've implemented this:

    func didDismissSearchController(_ searchController: UISearchController) {
        UIView.animate(withDuration: 0.25, animations: {
            self.collectionView?.contentInset = UIEdgeInsets(top: 64, left: 0, bottom: 0, right: 0)
        })
    }
    

    And it was good... smooth animation, until I've realized that the property searchController.hidesNavigationBarDuringPresentation is true, so all I have to do is set it to false.

    That's it, no need for contentInset or contentOffset animation! The final solution looks like this:

    @IBAction func showSearchBar(_ sender: UIBarButtonItem) {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        searchController.hidesNavigationBarDuringPresentation = false
        present(searchController, animated: true, completion: nil)
    }