views:

826

answers:

4

I have a UISearchBar which acts as a live filter for a table view. When the keyboard is dismissed via endEditing:, the query text and the gray circular "clear" button remain. From here, if I tap the gray "clear" button the keyboard reappears as the text is cleared.

How do I prevent this? If the keyboard is not currently open I want that button to clear the text without reopening the keyboard.

There is a protocol method that gets called when I tap the clear button. But sending the UISearchBar a resignFirstResponder message doesn't have any effect on the keyboard.

A: 

In your endEditing method, why don't you clear the UISearchBar and there? Since that must be where you resign first responder also, it makes sense.

Corey Floyd
I don't understand what you're trying to say. If I resign the searchbar like this: - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar { [searchBar resignFirstResponder]; }that doesn't work.
DASKAjA
A: 

Of of the search bar delegate calls asks you to accept a change from an old value to a new one - you could detect that the new value was nil, along with the old value being not-nil, and an indicator that the user had not typed anything since the keyboard was last up - then in that case resign first responder for the search bar. Not sure if the keyboard will momentarily display though.

I have a very similar situation and may try that myself.

Kendall Helmstetter Gelner
A: 

I've found that resignFirstResponder doesn't work when textDidChange is called from a touch to the "clear button". However, using performSelection: withObject: afterDelay: seems to be an effective workaround:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if ([searchText length] == 0) {
        [self performSelector:@selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
    }
}

- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar
{   
    [searchBar resignFirstResponder];   
}
Gregory Cosmo Haun
+2  A: 

Hi,

This is an old question and I just came across the same issue and managed to solve it the following way:

When the searchBar:textDidChange: method of the UISearchBarDelegate gets called because of the user tapping the 'clear' button, the searchBar hasn't become the first responder yet, so we can take advantage of that in order to detect when the user in fact intended to clear the search and not bring focus to the searchBar and/or do something else.

To keep track of that, we need to declare a BOOL ivar in our viewController that is also the searchBar delegate (let's call it shouldBeginEditing) and set it with an initial value of YES (supposing our viewController class is called SearchViewController):

@interface SearchViewController : UIViewController <UISearchBarDelegate> {
    // all of our ivar declarations go here...
    BOOL shouldBeginEditing;
    ....
}

...
@end



@implementation SearchViewController
...
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        ...
        shouldBeginEditing = YES;
    }
}
...
@end

Later on, in the UISearchBarDelegate, we implement the searchBar:textDidChange: and searchBarShouldBeginEditing: methods:

- (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)searchText {
    NSLog(@"searchBar:textDidChange: isFirstResponder: %i", [self.searchBar isFirstResponder]);
    if(![searchBar isFirstResponder]) {
        // user tapped the 'clear' button
        shouldBeginEditing = NO;
        // do whatever I want to happen when the user clears the search...
    }
}


- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)bar {
    // reset the shouldBeginEditing BOOL ivar to YES, but first take its value and use it to return it from the method call
    BOOL boolToReturn = shouldBeginEditing;
    shouldBeginEditing = YES;
    return boolToReturn;
}

Basically, that's it.

Best

boliva