Disconnecting the keyboard from the UISearchBar when the X button is pressed

I use the UISearchBar (but not the SearchDisplayController, which is usually used in combination), and I would like to remove the keyboard when you press the "X" button.

I followed TomSwift 's suggestion for a call when "X" is tapped, and this works fine. But the resignation of the first responder from the text field, as well as the call to the UISearchBar instance, as with resignFirstResponder , will not force the keyboard to leave.

Is there a way to get rid of the keyboard when the user presses the X button?

Here is what I did to get the β€œClear” message:

 - (void)viewDidLoad: { for (UIView* v in searchBar.subviews) { if ( [v isKindOfClass: [UITextField class]] ) { UITextField *tf = (UITextField *)v; tf.delegate = self; break; } } } 

Then I have my class setup to implement both UISearchBarDelegate and UITextFieldDelegate.

Having a class as a text field delegate allows me to get this call:

 - (BOOL)textFieldShouldClear:(UITextField *)textField { [textField resignFirstResponder]; [self.searchBar resignFirstResponder]; return YES; } 

I tried everything I could think of. The last thing I am trying to find is a way to output "searchBarCancelButtonClicked", which UISearchDelegate will call in my Controller class, but not sure how I could do this, since UISearchBar does not seem to have direct methods for being called with this name.

+17
iphone uitextfield uisearchbar
Nov 16 '10 at 1:37
source share
13 answers

Update:

Well, this is a complete hack, but I was able to get it to work. Basically, the code calls the handler for the cancel button. To make it work, I had to call the selector with a delay, and I'm not sure why it should have been. In addition, I had to write an accessory for the cancel button, as well as for the text field.

Again, this is a complete hack. I'm not sure I will do it myself in the application.

 // this in the context of the search bar - (UIButton*) cancelButton { for (UIView* v in self.subviews) { if ( [v isKindOfClass: [UIButton class]] ) return (UIButton*)v; } return nil; } // this is the textField delegate callback - (BOOL)textFieldShouldClear:(UITextField *)textField { [textField resignFirstResponder]; UIButton* cb = _searchBar.cancelButton; NSObject* target = [[cb allTargets] anyObject]; NSArray* actions = [cb actionsForTarget: target forControlEvent:UIControlEventTouchUpInside]; NSString* selectorName = [actions objectAtIndex:0]; SEL selector = NSSelectorFromString( selectorName ); [target performSelector: selector withObject: cb afterDelay: 0.1]; return YES; } 

Original answer:

How do you get a clear β€œX” button to display first? In my test case, I do not see its display ...

Try executing resignFirstResponder in the searchBar rather than in the text box.

+2
Nov 17 '10 at 0:22
source share
β€” -

Toms answer made me think. If it is so that the search bar is not the first Responder yet, when the user clicks the clear button, we can just wait until it appears, and then you will have resignFirstResponder; those. along the lines:

 - (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 hacks than Tom IMHO.

+70
Jan 31 '12 at 18:20
source share

It works:

 [searchBar performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1]; 
+6
Mar 20 '13 at 21:07
source share

Updated for SWIFT 3:

Suppose the user entered a string in the search field and clicked on x, the following code works to hide the keyboard when you press x

`

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { if searchBar.text == nil || searchBar.text == "" { searchBar.perform(#selector(self.resignFirstResponder), with: nil, afterDelay: 0.1) } } 

`

+3
Mar 25 '17 at 16:18
source share

You can resignFirstResponder to click the cancel button as.

 - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar { SearchBar.showsCancelButton =NO; } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [SearchBar resignFirstResponder]; } 
+2
Nov 16 '10 at 4:33
source share

Swift 2 Version:

 func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { // The user clicked the [X] button or otherwise cleared the text. if (searchText.characters.count == 0) { searchBar.performSelector("resignFirstResponder", withObject: nil, afterDelay: 0.1) } } 
+2
Nov 01 '15 at 1:08
source share

I found this in a previous question:

The clearButton UISearchbar button makes the keyboard appear

He must do exactly what you want to do.

+1
Nov 16 '10 at 4:52
source share

Try to avoid

 - (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar 

in your code we can solve this

+1
Mar 22 '12 at 11:30
source share

I used a combination of @radiospiel's answer, as well as the answer that @Tozar is related 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 
+1
Dec 08
source share

Shouldn't the user interface in the main thread be performselector:WithObject:afterDelay: 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]; } } 
+1
Feb 18 '14 at 15:13
source share

EDIT: Actually the delegate connected to the UISearchBar is broken below. Just subclass UISearchBar and overwrite the UITextField Delegate method.

=============================

I had to do this to access a UITextView

 for (UIButton* v in [self.searchBar.subviews[0] subviews]) { if ( [v isKindOfClass: [UITextField class]] ) { UITextField *tf = (UITextField *)v; tf.delegate = self; break; } } 
0
Oct 28 '14 at 18:33
source share

Credit Maxhs for the original answer: This is quick version 2.2: Work like a charm for me

 if searchBar.text == "" { dispatch_async(dispatch_get_main_queue(), { self.searchBar.resignFirstResponder() }) } 
0
Sep 16 '16 at 4:55
source share

Another point of view for transparent text flow (similar to @TomSwift, but more understandable to me and less complicated). In addition, I need to hide the Cancel button after exiting the search panel, implement a direct search (after each character) and a cover table before the user performs a search.

 //self.searchHoverView can cover table view //performSearchWithSearchBar: method for performing search #pragma mark - UISearchBarDelegate - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { [searchBar setShowsCancelButton:YES animated:YES]; self.searchHoverView.hidden = NO; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { if (searchText.length) { [self performSearchWithSearchBar:searchBar]; } else { UIButton *button; for (UIView *subView in [searchBar subviews]) { for (UIView *view in [subView subviews]) { if ([view isKindOfClass:[UIButton class]]) { button = (UIButton *)view; break; } } } if (button) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [button sendActionsForControlEvents:UIControlEventTouchUpInside]; }); } } } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { self.searchBar.text = nil; [self.searchBar setShowsCancelButton:NO animated:YES]; [self.searchBar resignFirstResponder]; self.searchHoverView.hidden = YES; } 
0
Nov 28 '16 at 11:51
source share



All Articles