I have a simple TableView with a search bar added. Everything works fine, except that when the view comes up (it's the first view in the app), the search bar is focused (or appears so), so that it shows the "Cancel" button (see image).
I've tried setting the tableview as first responder, calling resignFirstResponder on the search controller etc.
If you tap on the search bar and then hit cancel, the focus is removed and everything's fine - the "Cancel" button goes away.
Any ideas on why this is and how can I show a search bar that's not focused?
Add searchBar.resignFirstResponder() in viewDidLoad() method.
-Good Luck.
Based on the image, your textfield is not first responder and you just don't want to see cancel button
you can set searchBar.setShowsCancelButton = false
or in storyboard, uncheck Shows Cancel Button
then if you want to show cancel button during editing, check the UISearchBarDelegate methods:
func searchBarTextDidBeginEditing
and set searchBar.setShowsCancelButton = true
func searchBarCancelButtonClicked
and set searchBar.setShowsCancelButton = false
Related
I have a view controller with a UISearchController that, when tapped, will expand and bring up the keyboard. I want the user to press a button (separate from the search controller), when then brings up the search bar without actually tapping it. Is this possible?
What you want to achieve is to make the searchBar become the first responder. You can do that with:
searchController.searchBar.becomeFirstResponder()
I have a navigation bar with added searchbar icon.
Tapping the searchbar button instantiates the UISearchBarController.
Everything works fine, except that the 'Cancel' button tap propagates to the navigation bar button below (which closes the current modal).
Tapping cancel here:
Also taps done here:
I've witnessed that there is a delegate method available:
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
}
How do I stop the event from propagating?
Note: The propagation doesn't happen when tapping 'Cancel' after text was entered in the searchbar, only when it is empty. Very strange.
I think what you are seeing is that tapping Cancel when text is present is actually clearing out the text within the UITextField that the UISearchBar owns (as part of the UISearchController). Tapping Cancel otherwise is supposed to dismiss the search bar. From the Apple docs on searchBarCancelButtonClicked: it states that:
Typically, you implement this method to dismiss the search bar.
I've ran into this in the past with "search bar" functionality on a UITableViewController, and it's one of the reasons why I've switched over to using a standard UIViewController which owns a UITableView and owns a UISearchBar. I have a little bit more control, this way, over the content of my view controller, and the search bar I'm using with it.
Not sure if that directly helps you, but using a UISearchBar instead of a UISearchController might point you in a better direction like it did for me.
Rebooting the emulator fixed the problem, whatever that makes sense.
How to set SearchBar to be active after navigating back from another view controller?
Type the search string and click search button on search suggestion page, then this page popped by navigation controller. The search result page which was navigated back has a search bar with search text, and refresh the result table view.
But this SearchBar's cancel button is inactive, the first click make search bar become editing mode and the second click just can make it work.
How to set SearchBar's cancel button to be active, so I only need to click cancel button once.
Search suggestion page, will be popped
Search result page, cancel button, two states: active and inactive
If you're just trying to activate the search bar when it's parent view appears, then you can just add the following to the view controller that contains it:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if searchBar.canBecomeFirstResponder {
searchBar.becomeFirstResponder()
}
}
I have implemented UISearchController so that it appears overtop the UINavigationBar upon tapping a search icon. After filtering the table, the user should be able to select a row which will push a new view controller. The problem is upon doing so, the search controller is still being shown overtop the navigation bar.
I have researched this and it was suggested you should set self.definedPresentationContext to true. This does not work when the search bar is presented overtop the navigation bar. When you tap the search icon the keyboard appears but the search bar does not animate in.
Another option I found is to dismiss the search controller in viewWillDisappear, by setting active to false. The problem with this solution is it animates away during the push transition. And when you navigate back, the search is obviously no longer active, therefore the user has lost the search context and all results are shown.
I would like to know how to push a view controller, keep the search active, but not show the search interface overtop of the next view controller. Ideally the search interface would be pushed away to the left as the new view controller is pushed, and return upon swiping back to the search results.
I have tweaked Apple's UIKit Catalog sample code to show the undesired behavior. To reproduce the problem, download this project, run it on iPhone, tap the back button, select Search, select Present Over Navigation Bar, tap the search icon, type in a search term, and select a result. Notice the search bar remains visible. Here is the code from SearchPresentOverNavigationBarViewController.swift:
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if searchController.active {
//searchController.active = false //undesirably dismisses search, animates away during push, upon going back search is not active
}
}
#IBAction func searchButtonClicked(button: UIBarButtonItem) {
//self.definesPresentationContext = true //causes the search to not appear
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
presentViewController(searchController, animated: true, completion: nil)
}
I'm a little late to the show but I recently found myself in a similar situation and want to share my experience.
So let's say you have presented your search interface, the user has typed something into the search field and you have showed them some results. Upon selecting a result I push the new view controller to the original navigation controller, that is the navigation controller that contains the view controller which presented the search interface. When I do this, the search interface gets pushed to the left and when you tap the back button, the search interface is brought back and its state (query and results) is preserved.
I should mention that in the controller that contains the searchable content, the one that presents the search interface, I have enabled presentation context.
Also, my search bar is integrated in the header view of the table view that displays the search content, so I don't present the search interface explicitly - when the user taps inside the search field, it automatically goes up and pushes the navigation bar out of the screen. This is the only difference in our setups that I can think of. Anyways, hope this helps you. Cheers!
I have an app that has a toolbar, but I don't want the bar at the top, in order to free more viewing space. Therefore I have decided not to use a navigation controller. I'd like to add a back button to the toolbar. How would I go about this?
Adding the button is easy enough, and setting the action to performSegueWithIdentifier is all fine, but what happens is that the previous view just gets loaded again, rather than show it as it was, like a true back button. So if I tap on the 10th row on a tableView and go to a new page, when I press the back button it loads the view from the top again, instead of showing it as where I scrolled down to last.
Even though you don't want a UINavigationBar, you do want a UINavigationController in this case, because it manages the 'back stack' exactly the way you want it. Just hide its navigation bar by setting its navigationBarHidden property to true (in the Storyboard or in the viewDidLoad function of the root view controller).
You can then use navigationController.popViewController(true) as normal, in response to the user clicking your custom back button.