Exit the editing state after performing a search with Search Controller - ios

I'm using a search controller in order to implement a search section in an iOS app. I'm using iOS 11 and xCode 10.
My scene is a Table View Controller. I have included a search bar programmatically with the following code:
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
definesPresentationContext = true
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
I have also included a UISearchBar delegate extension:
extension SearchTableViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
tableView.reloadData()
episodeResultsArray = []
let searchTerm = searchBar.text!
let escapedSearchTerm = searchTerm.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
performSearch(forTerm: escapedSearchTerm)
}
}
The performSearch function connects to a database via AlamoFire and returns the results which are then listed in the Table View.
When I run the app, the table appears empty (as it should be initially). When I click on the search bar, it enters the editing state (the navigation bar collapses, the search bar sticks to the top, a Cancel button appears, and a translucent grey box covers the rest of the screen.
When I search for something, the results are succesfully listed in the table. However, even though the results are visible, I still remain in the editing state for the search bar. I need to click on the translucent box to exit the editing state and only then I am able to scroll through the results.
How can I exit the editing state after I click on Search so I'm able to scroll through the table as soon as I get the results?
I tried using searchBar.resignFirstResponder() but this only dismisses the keyboard. I also tried
searchBar.endEditing(true)
but even though the search bar loses focus, I'm still in the editing state.
Just to clarify, I need for this to work as a search from scratch, not as a filter, meaning not just showing a subset of results as I type.

Found the answer. The solution is to add
searchController.isActive = false

Related

How to force a UISearchControllers search bar to end "focused" state?

Im running into a problem when I preform a search, I can't get the search bar to reset from it's focused state (The background view is dimmed and the cancel button is still in the search bar. I want to clear the search bar and NOT have the background dimmed).
The view controller has the following (in the view did load):
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.placeholder = "Search here"
searchController.searchBar.searchBarStyle = .minimal
self.navigationItem.searchController = searchController
When I tap search, I get have the following:
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
searchBar.resignFirstResponder()
searchBar.text = ""
self.navigationItem.searchController?.resignFirstResponder()
}
The searchBar.endEditing(true) doesn't seem to be doing anything. Nor the resignFirstResponder. The background of the view is still dimmed.
For reference, the view controller is embedded in a nav controller, which in part a tab bar view controller (if that matters). And after the search is made, I push another view controller on the stack (hence why I want to clear the search bar and reset it's state when the view controller is shown again).
I've added some pictures to show the problem visually. The second photo is what Im left with after search is pressed when I want to to reset and look like the first photo.
self.navigationItem.searchController?.isActive = false is apparently what I'm looking for

UISearchBar ends editing, hides keyboard, but screen is still dimmed

I have a view controller in which I dynamically create a UISearchController and assign it to self.navigationItem.searchController.
class MyViewController: UIViewController, UISearchBarDelegate {
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.searchController = searchController
searchController.searchBar.delegate = self
// launch the app directly into this search text box
searchController.searchBar.becomeFirstResponder()
}
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
// I tried this
searchBar.resignFirstResponder()
// and this
searchBar.endEditing(true)
// and finally this
return true
}
}
The keyboard hides away when the user touches anywhere outside the searchbar and the screen goes back to its brightness. That is the expected behavior.
However, when the user taps the [Search] button within the on-screen-keyboard, the keyboard goes away, but the screen is kept dim. None of the sub-views are useable, except if the user taps the search bar again, then the keyboard comes back.
So in short, the only way for the user to continue using the view controller, is not to hit the [search] button, which is counter-intuitive.
am I missing something?
In viewDidLoad(), add the following line:
searchController.obscuresBackgroundDuringPresentation = false
From the documentation: If you use the same view controller to display the searchable content and search results, it is recommended that you set this property to false. The default value of this property is true.

isMovingFromParent property not set/false when search bar is active

xCode 10.2.1, iOS 12.1
I'm using a tableView with a searchbar. Everything is working fine, except a strange behavior when the navigationBar is visible during a search.
searchController.hidesNavigationBarDuringPresentation = false
When I leave the default setting (hidesNavigationBarDuringPresentation = true) the back button and title disappears, if I enter something into the searchbar. Then I have to press the search bar's cancel button and afterwards the back button. The Method viewWillDisappear() gets called and isMovingFromParent is set to true.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParent {
...
}
}
Everything works fine, I just don't like this behavior, to have to tap on cancel and on the back button.
I would like to enter a search string, see my results in my tableview, maybe select some of them and without tapping on the search bar's cancel button, just tap on the back button.
Therefore I set searchController.hidesNavigationBarDuringPresentation = false and tried it.
But when doing this isMovingFromParent is suddenly false.
Can someone please explain me why this happens, at least for me it makes no sense.

UISearchBar in UINavigationController

I am wondering to programmatically put a UISearchBar into UINavigationController, rather than replacing UINavBar title, as I want the large title to show up. See Files app on iOS.
Here is my .swift
class Search: UITableViewController, UISearchBarDelegate
override func viewDidLoad() {
super.viewDidLoad()
searchBar()
}
func searchBar() {
let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
navigationItem.searchController?.searchBar.placeholder = "search".localized
navigationItem.searchController?.dimsBackgroundDuringPresentation = false
navigationItem.hidesSearchBarWhenScrolling = false
}
The point is: by changing nil to actual searchResultsController, after typing text into search bar, the whole navigation controller (with search bar and typed text) got replaced by the searchResultsController view. No search bar while typing into it in short.
I am trying hard to use iOS 11/12 native look and feel within the app and putting the search bar into TableViewController is a no way here. Can someone help me?
If you don't need a different view controller to display the results simply use (it will not make your navigation bar disappear):
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
And do not change the value after that.
Most of your code is good, however you will need to implement the UISearchResultsUpdating protocol to detect updates (when the user write in the search bar) and use a table view (inside your view controller) to display the results of the search.
You do that by reloading the data of your table view inside the function: updateSearchResults(for searchController:) after filtering the data you want with the text inside the search bar. You can read this good tutorial on the subject for more information.

UISearchController dismisses VC upon hitting cancel button

So, I am currently trying to replace the depricated searchDisplayController in one of my projects with UISearchController and I am running into this problem.
If there are no results in the search (the UITableView is empty) the whole ViewController is dismissed. This does not happen when the search results are not empty. I wan't to make it clear I am not using a UITableViewController. Instead I have a regular VC with a UITableView in it.
Here is some of my code:
var resultSearchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.delegate = self
controller.searchBar.delegate = self
self.studentTable.tableHeaderView = controller.searchBar
return controller
})()
....
}
Now, if I add this function to the equation the cancel button always dismisses the VC.
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
resultSearchController.active = false
}
So why exactly does setting the searchController.active = false dismiss the VC? Is it because it is using the same UITableView as the VC? I believe that the old searchDisplayController would just display a UITableView over the one being used. If this is the case is there a way to override the dismissVC?
this is also Happening to me. The Way I Solve it is by Replacing:
resultSearchController.active = false
with
resultSearchController.searchBar.text = ""
resultSearchController.searchBar.resignFirstResponder()
I Hope this helps you :-)
2018 Just wanna share the fruits of my 1-2 hours debugging.
I had multiple issues with using UISearchController with UITabBarController, namely:
This one, this very question of the OP. Hitting cancel button dismisses the screen that is presenting the searchController.
The tab (or the screen) becomes black, Tab Bar and UISearchController giving black screen
Using UISearchController inside the title view of the navigation bar of UINavigationController in both iOS 10, 11, and 12, like this questions. UISearchBar increases navigation bar height in iOS 11
And for the solution for #3, since we're already here: https://stackoverflow.com/a/53264329/3231194
Finally, the ONLY solution that I have been seeing all this time is adding this code:
self.definesPresentationContext = true
The issue is that I was putting this in a wrong function.
Remember, that solution solved the #1, and #2 problem that I had. Nothing more, nothing less.
Where to add that? Inside the viewDidAppear. That's it!

Resources