I need to have a UISearchBar
above a UITableView
(ie. the search bar is not part of the table view), and what I found is that when the search bar is activated, it moves off screen.
I did a fair bit of search and could not find a solution, there are ‘search bar off screen’ issues but they are adding search bar to table's header view and tweaking properties like definesPresentationContext
fixed it.
My view hierarchy:
VC’s view |— top view |— segmented control |— search bar |— table view
Looks like UISearchController expects the search bar to be inside the table view, and always shifts the table view so that the search bar moves to the very top of screen.
Anyone having the same issue and found a solution?
Thanks a lot!
After further testing I decided to just implement the UISearchBar delegate and stop using the UISearchController since I was just reusing my UICollectionView for the results. Found a great guide on how three different methods to implement the SearchBar.
TLDR
Enable clips to bounds on the containing view. Or if you have a collection view cell that has a user-generated content view, enable clips to bounds on that content view.
Details:
An additional very important fact is that you may have the search bar embedded in a container view. This can cause issues if the container view does not have clips to bounds enabled. Other examples of this being a problem is the user-generated content views in UICollectionViewCells. Compare the setting on a UITableViewCell auto-generated content view to observe the difference.
Summary
A Boolean value that determines whether subviews are confined to the bounds of the view. Declaration
var clipsToBounds: Bool { get set } Discussion
Setting this value to true causes subviews to be clipped to the bounds of the receiver. If set to false, subviews whose frames extend beyond the visible bounds of the receiver are not clipped. The default value is false.
In my case, this was happening both inside a UICollectionView and inside of a UIStackView. I was able to keep my searchBar in place after noticing the following info in the searchBar quick help.
Summary
The search bar to install in your interface. Declaration
var searchBar: UISearchBar { get } Discussion
Before presenting your searchable content, install the search bar in this property somewhere into your view controller’s interface. The search bar becomes the starting point for searching your contents. Interactions with the search bar are handled automatically by the UISearchController object, which notifies the object in the searchResultsUpdater property whenever the search information changes. To use a custom subclass of UISearchBar, subclass UISearchController and implement this property to return your custom search bar.
After that I was able to resolve the issue successfully by doing the following:
let searchController = UISearchController(searchResultsController: nil)
var searchBar:UISearchBar!
Sometime later I assign the searchBar from the searchController to the searchBar in my UIViewController...
BTW - I embed my searchBar in a container UIView that has all the contraints I need to keep it in place.
func setupSearchController<T:UIViewController>(delegate vc:T) where T: UISearchResultsUpdating, T:UISearchBarDelegate {
searchBar = searchController.searchBar //this is the key
searchController.searchResultsUpdater = vc
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search".localized()
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = vc
searchController.searchBar.showsCancelButton = true
definesPresentationContext = true
self.searchMenu.addSubview(searchBar)
//searchMenu is a constrained UIView in my hierarchy
}