In my app, I used to have a search bar in the header view of my table view. However, I have added a search bar button item, and when a user taps it, I want a search bar to animate across the navigation bar, and the user should be able to search. This is kind of like the search bar in the Twitter iOS app. here is the code for my UISearchController:
self.searchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.hidesNavigationBarDuringPresentation = true
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
//self.tableView.tableHeaderView = controller.searchBar
self.definesPresentationContext = true
controller.searchBar.returnKeyType = .Search
controller.searchBar.delegate = self
return controller
})()
Here is how my UINavigationBar looks like right now:
How would I go about doing this?
You're almost there. You need to do four things:
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.titleView = searchController.searchBar
hide all the current UIBarButtonItems you have in the navigation bar
searchController.searchBar.becomesFirstResponder()
That is, you setup your UISearchController so it doesn't hide the navigation bar, as the UISearchBar is gonna be displayed there.
Then, when your IBAction runs, you do something like:
navigationItem.hidesBackButton = true
navigationItem.titleView = searchController.searchBar
navigationItem.rightBarButtonItem = nil
searchController.searchBar.becomeFirstResponder()
That guarantees the UISearchBar will use the entire UINavigationBar when it becomes the first responder. You also get the UISearchBar animation, which does a good job in hiding the unanimated removal of the UIBarButtonItems.
You will need to implement the UISearchBarDelegate (or if you prefer UISearchControllerDelegate) to restore the original navigation bar state once the user is done with the search.
One very important detail is that in order for your UISearchBar to be editable in the titleView, no other view controller can be set with definesPresentationContext = true at the time yours is pushed.
Related
I have a UISearchBar embedded in the NavigationItem, like so:
let search = UISearchController(searchResultsController: nil)
search.searchBar.delegate = self
search.hidesNavigationBarDuringPresentation = false
search.definesPresentationContext = false
search.delegate = self
navigationItem.searchController = search
And I also have a collectionView.
When I push a viewController from the collectionview, and then go back, I can't see the UISearchBar anymore.
Any way of fixing this?
Upgrading our application to support iPhone X. How can I add a search bar to the header of a table view and have it within the safe zone? Here is how we currently build the search bar.
let searchController = UISearchController(searchResultsController: nil)
func buildSearchBar() {
self.searchController.searchResultsUpdater = self
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.dimsBackgroundDuringPresentation = false
self.searchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = searchController.searchBar
self.definesPresentationContext = true
}
This topic is discussed explicitly in Building Apps for iPhone X video. (Designing for iPhone X also a good video.)
Bottom line, Apple suggests using navigation controller and showing it there:
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
if #available(iOS 11, *) {
navigationItem.searchController = searchController
searchController.isActive = true
} else {
present(searchController, animated: true)
}
(By the way, even in the absence of a navigation controller, present-ing the search controller, rather than setting it to be the table header, can prevent it from scrolling out of the safe area.)
Unclear what you mean by "within the safe zone". The table view can scroll, so the search bar is not necessarily "within" any part of the screen; it can be scrolled up behind the sensor area and on beyond.
You'll notice, however, that the native apps do not put the search bar as the header of the table. They put it in the navigation bar. You should do the same. Put the search bar into the navigation bar by setting the searchController of the navigationItem.
I know how to initialise the UIsearchcontroller by doing this:
let searchResultsController = UITableViewController(style: .Plain) as UITableViewController
searchResultsController.tableView.delegate = self
searchResultsController.tableView.dataSource = self
searchController = UISearchController(searchResultsController: searchResultsController)
so,
I have a button on navigation bar and on press I want to display SearchBar using UISearchController and then dismiss the search bar on tapping again on the search button or empty space of screen.
According to documentation, changing active property of search controller will move search bar to navigation bar
I'm trying to keep the search bar in view as the table scrolls. At the moment I'm placing it as the header in a tableview, and it works as it should, but of course the search bar scrolls off screen as you go down the table. I thought I could do this simply modifying this code sample:
How do I use UISearchController in iOS 8 where the UISearchBar is in my navigation bar and has scope buttons?
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
tableview.tableHeaderView = searchContoller.searchBar // How to put it elsewhere?
//Alternative that also works
navigationItem.titleView = searchController.searchBar
The idea was to take some other view and do
otherview = searchController.searchBar
For instance an outlet to a UISearchBar, or a blank UIView, or something like that.
But it doesn't show the searchBar if I do that. It seems to only work as the header view of a table or as a navigationItem.titleView.
Am I missing something?
If you have a blank UIView that is placed above the tableview.
let's assume you have an outlet to that blank UIView called searchContainer.
Then you can add the search bar of the UISearchController to that view by adding the following line
searchContainer.addSubview(searchController.searchBar)
I AM NOT USING STORYBOARD SEGUES.
When I use UISearchController to have a search bar at the top of my table view, I get extremely strange behavior. Is there documentation on how I'm supposed to handle the search bar when a view dismisses? When I switch to a new view controller via an animation or push one on a nav stack, the bar is stuck in its spot until I hit the "Cancel" button.
See a video of what's happening in this short clip:
https://www.youtube.com/watch?v=6G7xFMENm_o&feature=youtu.be
This is the code, in the view controller, that sets up search bar:
var s: UISearchController!
private func configureSearching() {
s = UISearchController(searchResultsController: nil)
s.searchResultsUpdater = self
s.dimsBackgroundDuringPresentation = false
s.searchBar.searchBarStyle = .Minimal
s.hidesNavigationBarDuringPresentation = false
tableView.tableHeaderView = s.searchBar
s.searchBar.sizeToFit()
}
you should add the following line in viewDidLoad
self.definesPresentationContext = true