0

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)
}
gutaker
  • 181
  • 3
  • 10
  • As I recall UISearchController has a delegate method, something like becomeActive. Have you tried to change the insets of the collectionView in that method? – haik.ampardjian Jun 13 '17 at 12:46
  • That doesn't look at all correct... How do you have two status bars? Can you create a small project that reproduces this result? – DonMag Jun 13 '17 at 13:09
  • These are not Status Bars, it's Top Bar. When UISearchController gets called, as in code above, it replaces standard Top Bar with UISearchBar interface. Once UISearchBar is dismissed with **Cancel** button, the standard Top Bar is back. – gutaker Jun 13 '17 at 19:53

1 Answers1

0

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)
}
gutaker
  • 181
  • 3
  • 10