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条回答
家丑人穷心不美
2楼-- · 2019-02-01 00:53

This works:

[searchBar performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1];
查看更多
手持菜刀,她持情操
3楼-- · 2019-02-01 00:53

I found this in a previous question:

UISearchbar clearButton forces the keyboard to appear

It should do exactly what you want to do.

查看更多
放我归山
4楼-- · 2019-02-01 01:01

Update:

Well, this is a total hack but I was able to make it work. Basically the code invokes the handler for the cancel button. To make it work I had to invoke the selector with a delay, and I'm not sure why this had to be. Also, I had to write an accessor for the cancel button just like you did for the text field.

Again, this is a total hack. I'm not sure I'd do this myself in an app.

// 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 the clear 'X' button to display in the first place? In my test case I dont see it displaying...

Try doing a resignFirstResponder on the searchBar, not the textField.

查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-02-01 01:02

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];
    }
}
查看更多
来,给爷笑一个
6楼-- · 2019-02-01 01:05

Try to avoid

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar

method in your code we can solve this

查看更多
SAY GOODBYE
7楼-- · 2019-02-01 01:08

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;
    }
}
查看更多
登录 后发表回答