UISearchController search bar text disappears when losing focus - ios

I'm using the UISearchBar of a UISearchController in the header of a UITableView. My searching works OK in that when I enter some text in the search bar's field, all the relevant methods are called and the table view shows the correct search results as expected.
The problem comes when I want to tap on one of the results to do something with it. As soon as I tap on one of the table view cells, the field in the search bar becomes empty. Since the search text is now empty, the search results are updated and the table view reloads with zero results. So the tap on the table cell does nothing, because the table cell no longer exists.
I can work around most of this problem by updating my updateSearchResultsForSearchController: method to not update the search results when the search string is empty. And this works fine. But in any case, I do still want the search text to remain in the search field, and this is the crux of my question...
Why is my search text disappearing from the search field, and how can I prevent the search field from becoming empty when I tap elsewhere?
Here's how I set up the search bar and search controller:
- (void)viewDidLoad {
[super viewDidLoad];
searcher = [[UISearchController alloc] initWithSearchResultsController:nil];
searcher.searchResultsUpdater = self;
searcher.delegate = self;
searcher.definesPresentationContext = YES;
resultsTable.tableHeaderView = searcher.searchBar;
EDIT: I notice that the table view cells are dimmed while the search bar has focus. So I think that the search controller is capturing all touches and perhaps handles them as 'cancel' actions. If so, how do I stop it cancelling in this way?

Figured it out. I needed to add:
searcher.obscuresBackgroundDuringPresentation = NO;

Related

Can I have a UISearchBar be its own .inputAccessoryView?

I need simple text input to aid in data filtering. Ideally I'd like to keep a strong reference to a UISearchBar, and when the user taps "Search", then this searchBar would becomeFirstResponder() and I would set
self.searchBar.inputAccessoryView = self.searchBar
But that doesn't seem to work. The .searchBar is generally not in the view controller's view hierarchy, and is something I would just hope to attach to the keyboard.
Otherwise I'll think of another approach. Ultimately I'm just trying to have text input that I can see while editing, and that should be attached to the toolbar. Ideally with an .inputAccessoryView so I don't have to bother with keyboard notifications / animations
Does anyone know if this is possible?
If I understand you correctly, you want to use the search bar both for triggering a keyboard and for showing the search term entered by the user, but do not want to always have the search bar on-screen but have it activated via a "Search" button.
That's not possible with a single UISearchBar, but you can just use two of them:
Add one as subview to your view controller and hide it (bar1), and use the second as inputAccessoryView (bar2); you should become delegate of both search bars.
When the user presses the "Search" button make bar1 become first responder, handle its events via the delegate protocol, and update the bar2 accordingly.
Prevent the user from directly entering text in bar2 by blocking it
with the shouldChangeTextIn delegate method. Other events that are
received in bar2 could be forwarded to bar1 where this makes sense for you.
To get you started, here's some code for the basic setup (which would go in e.g. viewDidLoad):
self.dummySearchBar = UISearchBar()
dummySearchBar.isHidden = true
dummySearchBar.delegate = self
self.visibleSearchBar = UISearchBar()
visibleSearchBar.delegate = self
dummySearchBar.inputAccessoryView = visibleSearchBar
Then, in your "Search" button handler, let the keyboard with the attached search bar appear like this:
dummySearchBar.becomeFirstResponder()
Note: I have a similar setup in a project but for simplicity I use UITextFields instead of UISearchBars; still, I think the basic approach should work with UISearchBars as well.
add toolBar to searchBar
searchBar.inputAccessoryView = toolBar
hide keyboard
searchBar.endEditing(true)

How to trigger the "cancel search" when using only a UISearchBar?

I have a table view with a header that displays a UISegmentedControl and a UISearchBar. Keep in mind that I am not using a UISearchController. When I have searched the current list, and I toggle a different segment, I want to cancel the search and reload the list with the new data.
Currently I am manually clearing the search text, animating the cancel button and hiding the keyboard. But I am also doing that inside my searchBarCancelButtonClicked method.
Is there a way to programmatically cancel the search (clearing the text, hiding the keyboard, and hiding the cancel button) when only using a UISearchBar?
No, there's no way to automatically clear the text field, hide the keyboard, etc. Even though it seems like common functionality, it's up to each developer to decide how to implement it. Apple just provides the ability to catch the event when the user taps the Cancel button.
Typically, I'll create a local function in the view controller like:
-(void)clearSearchBar:(UISearchBar *)searchBar {
searchBar.Text = #"";
[searchBar resignFirstResponder];
...
}
Then, in searchBarCancelButtonClicked: (assuming you've created an IBOutlet for the search bar), you can do this:
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self clearSearchBar:self.searchBar];
}
You can then also call clearSearchBar: anywhere else you need to clear it.
Obviously, there's room to use categories here to avoid duplicating code.
You could also just call searchBarCancelButtonClicked: like this:
[self.searchBar.delegate searchBarCancelButtonClicked:self.searchBar];

Search freezes in UISearchBar with searchDisplayController

I have a UISearchDisplayController working nicely with a UISearchBar. shouldReloadTableForSearchString correctly returns results as the user types, but when the user hits the Search button on the keyboard and searchBarSearchButtonClicked is triggered, something odd happens after the final search results correctly display and the user hits Cancel on the search bar. Once the user reactivates search, the search opens but the cursor doesn't blink, the search results don't display and the keyboard looks locked on every keypress as shown in the attached image. There should be results for "Test", but nothing is happening and something seems to be held up b/c the last pressed key ("T") isn't going back down to the keyboard.
I'm holding off on including code b/c there are a lot of moving parts, but if any code would help, i can quickly include it. Thanks for your help.
UPDATE: it's not just after the user submits the query - if they've touched the resulting searchDisplayController.searchResultsTableView after inputting a query to scroll down through the results, and then hit Cancel, they'll see the frozen cursor and broken search once they activate the searchBar again (same image applies).
SECOND UPDATE: this only happens when I hide / unhide the navbar while search is active in viewWillLayoutSubviews. Any ideas? Really appreciate any help!
-(void)viewWillLayoutSubviews {
if (self.searchDisplayController.isActive && !profileSelected) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
else {
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
}
LAST UPDATE: when hide/unhide code is placed into searchDisplayControllerWillBeginSearch and searchDisplayControllerWillHideSearch respectively, the searchBar incorrectly unhides 20px below navbar:
fixed it by adding this code:
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self.searchDisplayController.searchBar becomeFirstResponder];
}
UISearchDisplayController is using UITableView to show search results. Whenever you scroll or new cells are loaded, viewWillLayoutSubviews is getting called. This is causing the app to freeze. Try moving you setNavigationBarHidden code in a separate method triggered by some other action.

UISearchBar for UISearchController iOS 8 regain focus after resignFirstResponder

I'm using the new UISearchController in iOS 8.
I have a UISearchBar which I've added to the titleView and a corresponding results controller.
I have it set up so that when the search results are scrolled scrollViewWillBeginDragging(), I call searchBar.resignFirstResponder() to hide the keyboard (same as Spotlight search, Facebook app, etc. -- let's us see the results hidden behind the keyboard).
The problem I have is that I can't seem to be able to re-gain focus on the search bar. It should be as simple as just tapping on the search bar, but this seems to end the search completely, rather than refocusing the search bar to allow the search text to be edited.
I can't figure out why the UISearchBar isn't regaining focus.
Any suggestions?
Turns out after much trial and error, the solution is surprisingly simple:
Just set dimsBackgroundDuringPresentation = false on your UISearchController and it all works fine!

Do not show searchResultsTableView before search button clicked

I'm trying to solve this problem with no luck. I have a search bar and search a display controller inside table view controller.
Everything works fine - I make the server call to search the endpoint when user clicks the "Search" button and display the results. But the problem is I do not want to show No results in the table view before user clicks Search.
Instead of that I prefer to show default dark overlay.
You could return 1 in numberOfRowsInSection while the query is in progress and leave the dummy cell empty or set its hidden property to YES so it is not visible. So you have do not have "No Results" showing up.
Also for making it a dark overlay try something like this:
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView{
tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"default.png"]];
}
More information: Link!

Resources