Note 1: This question pertains to adding a UISearchController's search bar outside of the table view it updates - NOT as the table view's header.
Note 2: Some trial and error led me to a solution. Please see my answer below.
I am new to iOS development and am struggling to work with the UISearchController class. I have a view controller, and in my view controller's view, I plan to have a search bar above a table view. I would like the search bar to be linked to a UISearchController. Since interface builder does not come with a UISearchController, I am adding the controller programmatically. After instantiating a UISearchController, I have tried to add the search controller's search bar to my view programmatically but have not been successful. I have tried setting the search bar's frame and giving it autolayout constraints, but neither approach has worked for me (i.e. when I run the app, nothing appears). Here is the latest code I have tried:
let searchController = UISearchController(searchResultsController: nil)
// Set the search bar's frame
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 50)
// Constraint to pin the search bar to the top of the view
let topConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
searchController.searchBar.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(searchController.searchBar)
self.view.addConstraint(topConstraint)
Any help would be greatly appreciated! Thank you!
EDIT: Using only one of either setting the search bar's frame or you giving it autolayout constraints (as opposed to a combination both as I initially tried) appears to work at first, but after tapping on the search bar you will have issues as pointed out by Dwight. I've left the code for these cases in case it's helpful to compare to what you currently have, but for a working solution see my answer below.
Using autolayout constraints:
let searchController = UISearchController(searchResultsController: nil)
let topConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: (statusBarHeight + navigationBarHeight!))
let leftConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0)
let heightConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 44)
searchController.searchBar.setTranslatesAutoresizingMaskIntoConstraints(false)
searchController.searchBar.addConstraint(heightConstraint)
self.view.addSubview(searchController.searchBar)
self.view.addConstraints([topConstraint, leftConstraint, rightConstraint])
I've set the topConstraint constant to the height of the status bar plus the height of the navigation bar, as my view controller is embedded in a navigation controller.
Adjusting the frame:
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.frame = CGRect(x: 0, y: (statusBarHeight + navigationBarHeight!), width: self.view.frame.size.width, height: 44)
self.view.addSubview(searchController.searchBar)
try this:
or you can just do this:
After some more trial and error, I have the following working solution:
var searchController: UISearchController!
Then, in viewDidLoad(), you will need:
This should be it! Of course, you'll need to make your view controller a UITableViewDatasource, UITableViewDelegate, UISearchBarDelegate, UISearchControllerDelegate, and UISearchResultsUpdating and take care of all required delegate methods as well, but as far as the search bar goes, this has worked for me. Please comment if you have any issues.