Search freezes in UISearchBar with searchDisplayController - ios

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.

Related

UISearchController search bar text disappears when losing focus

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;

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];

Can't get UILabel to display from boolean condition

I can't for the life of me figure out why this won't work. I'm trying to display a label after determining a boolean condition. No matter what I do, the label won't display. So in a pathetic desperate attempt, I put the code to display the label inside a button event to force it to display. Now it works perfectly (from the button click). But it still won't work from the boolean condition!
This is in viewDidLoad (note that the 'true' is just to isolate where the fault is):
if (true) [self showSubscribeLabel];
This is from the button click:
- (IBAction)askUserToSubscribe:(id)sender {
[self showSubscribeLabel];
}
-(void) showSubscribeLabel {
NSLog(#"here");
self.subscribeLabel.hidden = NO;
[self.view bringSubviewToFront:self.viewUnauthorized];
}
I see the output here when the controller loads and then again after clicking the button. What am I doing wrong? Thanks!
You should move your test and method invocation to viewWillAppear - often things aren't fully initialised in viewDidLoad. Having the code in viewWillAppear will also ensure that the condition is evaluated every time the view controller appears (such as when another view pops off a navigation stack) rather than when it is loaded for the first time.

UIRefreshControl behaves differently after adding UISearchBar

I'm using a UITableViewController subclass in iOS 7.
Before I added the search bar as the table view's tableHearerView, the UIRefreshControl worked as I expected: I triggered beginRefreshing in viewDidLoad and I could see it spinning every time I entered this screen.
After I added the search bar, I can't see UIRefreshControl spinning when I enter this screen. Everything else seems to work fine, e.g pulling down will show the spinning UIRefreshControl.
Did I use the 2 widgets in right way? How to fix this issue so I can see the spinning like what I saw before adding the search bar?
Thanks a lot in advance!
It looks like if you invoke the beginRefreshing method manually you also need to set the offset of the tableView manually.
Here is the solution in Objective-C:
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
and here the solution in Swift:
self.tableView.setContentOffset(CGPointMake(0, -self.refreshControl!.frame.size.height), animated:true)

Getting notified when user presses "Search" on keyboard in UISearchDisplayController

I am using a UISearchDisplayController to let the user search through a list of buildings on a university campus. Sometimes, the user will know exactly what building they want, enter the building's number, and that building will then be the only building result showing in the UITableView. At the moment, if the user proceeds to hit "Search" on the keyboard, the keyboard animates off the screen and the user then has to make a second tap on the sole item in the UITableView to be sent to a point on a map showing the location of that building.
My question is, is there a way to be notified when the user hits the "Search" button on the keyboard inside a UISearchDisplayController, so that I can perform a check to see if there's only one result, and if so, take the user straight to that result, rather than requiring them to explicitly make the second tap? I've looked at the methods provided by the UISearchDisplayDelegate, but can't see anything relevant.
UISearchDisplayController has a UISearchBar, you can set a delegate for search bar and implement -searchBarSearchButtonClicked:.
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
}
This also works with the keyboard search button.

Resources