I\'m using the UISearchBar (but not the SearchDisplayController that\'s typically used in conjunction) and I\'d like to dismiss the keyboard when you hit the \'X\' button.
I used a combination of @radiospiel's answer and also the answer that @Tozar linked to:
@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;
}
}
...
- (void) searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
// TODO - dynamically update the search results here, if we choose to do that.
if (![searchBar isFirstResponder]) {
// The user clicked the [X] button while the keyboard was hidden
shouldBeginEditing = NO;
}
else if ([searchText length] == 0) {
// The user clicked the [X] button or otherwise cleared the text.
[theSearchBar performSelector: @selector(resignFirstResponder)
withObject: nil
afterDelay: 0.1];
}
}
- (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;
}
@end
Try to avoid
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
method in your code we can solve this
I found this in a previous question:
UISearchbar clearButton forces the keyboard to appear
It should do exactly what you want to do.
EDIT: Actually, the below breaks the delegate that is connected to UISearchBar. Just subclass UISearchBar and overwrite the UITextField Delegate method.
===========================
I had to do this to get access to the UITextView
for (UIButton* v in [self.searchBar.subviews[0] subviews])
{
if ( [v isKindOfClass: [UITextField class]] )
{
UITextField *tf = (UITextField *)v;
tf.delegate = self;
break;
}
}
Shouldn't UI changes be made on the main thread instead of using performselector:WithObject:afterDelay:
?
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if (searchText.length == 0) {
[searchBar performSelectorOnMainThread:@selector(resignFirstResponder) withObject:nil waitUntilDone:NO];
}
}
Toms answer got me thinking. If it is that the search bar is not yet the firstResponder when the user clicks the clear button we can just wait until it is, and then have it resignFirstResponder; i.e. along the lines of:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self performFilteringBySearchText: searchText]; // or whatever
// The user clicked the [X] button or otherwise cleared the text.
if([searchText length] == 0) {
[searchBar performSelector: @selector(resignFirstResponder)
withObject: nil
afterDelay: 0.1];
}
}
Works like a charm, and less hacky than Tom's IMHO.