Dismissing keyboard from UISearchBar when the X bu

2019-02-01 00:28发布

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've followed TomSwift's suggestion on getting called when the 'X' is tapped and that works great. But resigning first responder from the text field and also invoking in the UISearchBar instance, both with resignFirstResponder, won't make the keyboard go away.

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

Here's what I did to get the 'Clear' notify:

- (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 the class serve as the textfield delegate allows me to get this call:

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

I've tried everything I can think of. The last thing I'm trying is to find a way to issue the 'searchBarCancelButtonClicked' that UISearchDelegate will invoke on my Controller class but not I'm sure how I could do this since the UISearchBar doesn't seem to have any direct methods to invoke with this name.

13条回答
The star\"
2楼-- · 2019-02-01 01:09

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)
        }
    }
查看更多
Deceive 欺骗
3楼-- · 2019-02-01 01:09

Credit to Maxhs for original answer : This is swift 2.2 version : Work like charm for me

if searchBar.text == "" {
                dispatch_async(dispatch_get_main_queue(), { 
                    self.searchBar.resignFirstResponder()
                })
            }
查看更多
ゆ 、 Hurt°
4楼-- · 2019-02-01 01:09

Another point of view for clear text flow (similar to @TomSwift answer but clearer for me and less tricky). Also, I need to hide Cancel button after exit from the search bar, implement live search (after each symbol) and cover table before user complete 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;
}
查看更多
狗以群分
5楼-- · 2019-02-01 01:12

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
查看更多
看我几分像从前
6楼-- · 2019-02-01 01:14

Updated for SWIFT 3:

Suppose that the user has entered a string in searchfield and clicks x the following code works to hide keyboard when x is pressed

`

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

`

查看更多
神经病院院长
7楼-- · 2019-02-01 01:16

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.

查看更多
登录 后发表回答