点击X按钮时从UISearchBar中解除键盘

时间:2010-11-16 01:37:02

标签: iphone uitextfield uisearchbar

我正在使用UISearchBar(但不是通常联合使用的SearchDisplayController),我想在点击“X”按钮时关闭键盘。

当点击'X'并且效果很好时,我跟着TomSwift's suggestion被叫了。但是,从文本字段中退出第一个响应者并在UISearchBar实例中调用resignFirstResponder,都不会使键盘消失。

当用户轻敲X按钮时,有没有办法摆脱键盘?

以下是我通过“清除”通知所做的工作:

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

然后我有我的类设置来实现UISearchBarDelegate和UITextFieldDelegate。

将课程作为文本字段委托,我可以接听此电话:

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

我已经尝试了我能想到的一切。我正在尝试的最后一件事是找到一种方法来发出UISearchDelegate将在我的Controller类上调用的'searchBarCancelButtonClicked',但不是我确定我怎么能这样做,因为UISearchBar似乎没有任何直接的方法用这个名字调用。

14 个答案:

答案 0 :(得分:71)

汤姆斯回答让我思考。如果用户点击清除按钮时搜索栏还不是第一个响应者,我们可以等到它,然后让它resignFirstResponder;即沿着:

- (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];
  }
}

像汤姆的恕我直言,像魅力一样,不那么狡猾。

答案 1 :(得分:6)

这有效:

[searchBar performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1];

答案 2 :(得分:3)

Swift 2版本:

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)
        }
    }

答案 3 :(得分:3)

更新了SWIFT 3:

假设用户在搜索字段中输入了一个字符串并单击了x,以下代码可以在按下x时隐藏键盘

`

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

`

答案 4 :(得分:2)

您可以点击取消按钮resignFirstResponder。

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar

{

    SearchBar.showsCancelButton =NO;

}


- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{

    [SearchBar resignFirstResponder];


}

答案 5 :(得分:2)

<强>更新

嗯,这完全是黑客,但我能够让它发挥作用。基本上,代码调用取消按钮的处理程序。为了使它工作,我不得不延迟调用选择器,我不知道为什么这是必须的。另外,我必须为取消按钮编写一个访问器,就像你为文本字段所做的那样。

同样,这是一次彻底的黑客行为。我不确定自己是否会在应用程序中自己这样做。

// 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;
}

原始回答:

如何在第一时间显示清晰的“X”按钮?在我的测试用例中,我没有看到它显示...

尝试在searchBar上执行resignFirstResponder,而不是textField。

答案 6 :(得分:1)

我在上一个问题中找到了这个:

UISearchbar clearButton forces the keyboard to appear

它应该完全按照你想要做的去做。

答案 7 :(得分:1)

尽量避免

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
代码中的

方法我们可以解决这个问题

答案 8 :(得分:1)

我使用@ radiospiel的答案以及@Tozar linked给出的答案:

@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

答案 9 :(得分:1)

不应在主线程上进行UI更改而不是使用performselector:WithObject:afterDelay:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if (searchText.length == 0) {
        [searchBar performSelectorOnMainThread:@selector(resignFirstResponder) withObject:nil waitUntilDone:NO];
    }
}

答案 10 :(得分:0)

编辑:实际上,下面会破坏连接到UISearchBar的委托。只需子类化UISearchBar并覆盖UITextField Delegate方法。

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

我必须这样才能访问UITextView

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

答案 11 :(得分:0)

感谢Maxhs的原始回答: 这是swift 2.2版本: 像我一样的魅力

if searchBar.text == "" {
                dispatch_async(dispatch_get_main_queue(), { 
                    self.searchBar.resignFirstResponder()
                })
            }

答案 12 :(得分:0)

清晰文本流的另一种观点(类似于@TomSwift的回答,但对我来说更清晰,更不用说)。此外,我需要在退出搜索栏后隐藏取消按钮,在用户完成搜索之前实施实时搜索(在每个符号之后)和覆盖表。

//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;
}

答案 13 :(得分:0)

单击“ x”按钮时,搜索栏文本字段中的字符串将成为一个空字符集合。

检查集合的长度有助于检测何时单击了“ x”按钮。

我遇到了类似的问题,该解决方案对我有用:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    //let searchText = searchText.trimmingCharacters(in: .whitespaces)
    if searchText.isEmpty{
        DispatchQueue.main.async { [weak self] in
            guard let self = self else{ return }
            self.searchBar.resignFirstResponder()
        }
    }
}