views:

2381

answers:

3

I have a UISearchBar and on the delegate method I hide the keyboard when the text field is cleared:

- (void)searchBar:(UISearchBar *)filterBar textDidChange:(NSString *)filterText {
    NSLog(@"filter: %@", filterText);

    if ([filterText length] == 0) {
        NSLog(@"hiding keyboard");
        [filterBar resignFirstResponder ];

Now when I use the backspace button to clear out the search term all is good. The keyboard hides when the search turns to empty. Not so when I am pressing the "cross" button to clear out the search field altogether.

Well, not entirely true. I does call resignFirstResponder and hides the keyboard - you just can't see it because it comes right back up. I found this out by observing the keyboard show/hide events.

So how come the keyboard is shown again? How can I prevent this?

I've already tried to walk all subviews of the UISearchBar and also call resignFirstResponder on those ...but unless I did something wrong - that doesn't solve this either.

Update:

In fact I just got the keyboard to not disable the "Done" button :-D ...so I will "stop" going down that road as Kevin suggested. Still I would like to know why the keyboard came back up like this.

+1  A: 

I would suggest you stop trying to do this. Hiding the keyboard when the field empties out is completely non-standard behavior and the user won't expect it. In situations like this it's far better to keep your behavior consistent with all the rest of the apps across the system.

Kevin Ballard
I would love to ...but unfortunately the keyboard's "Done" button gets disabled when the text length is 0. Using an extra "Cancel" button is not only counterintuitive and much worse from the user experience but also kills the required screen realestate. Also see http://www.thismuchiknow.co.uk/?p=85
tcurdt
A: 

I basically agree with Kevin, but that doesn't help you so here goes:

Try looping through the subviews of the searchbar and find the sibling which is of the class UITextField. Then either set the delegate property of this text field to your ViewController's class and handle the callback there (e.g. textViewShouldReturn), or simply call resignFirstResponder directly on the text field. The former obviously needs to be done at init/load time while the latter can be done in your existing textDidChange callback.

Here are some more pointers:

http://discussions.apple.com/thread.jspa?threadID=1479468&tstart=0 http://discussions.apple.com/thread.jspa?messageID=8176608

Erik Abele
"I've already tried to walk all subviews of the UISearchBar and also call resignFirstResponder on those ...but unless I did something wrong - that doesn't solve this either." ...so you sure this works?
tcurdt
Yes, I'm sure that it worked half a year ago when I was in a similar situation - I never went down that route though and removed that code later on - but my svn logs tell me that it worked at that time :-)
Erik Abele
+1  A: 

I see you've accepted an answer and don't plan to continue in this vein, but I am curious whether you could achieve something like you wanted by implementing this:

- (BOOL)canBecomeFirstResponder
{
   return !preventingKeyboardAppearance; // so to speak
}

- (void)searchBar:(UISearchBar *)filterBar textDidChange:(NSString *)filterText 
{
   // handle text

   preventingKeyboardAppearance = YES;
   [filterBar resignFirstResponder];
}

I'm not clear under what circumstances you would set preventingKeyboardAppearance back to NO, but I do wonder if this would work.

Amagrammer