搜索栏中的 x 按钮被按下

44

如何处理按下“x”按钮时的事件?

我尝试了这个方法但不起作用。

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

}

输入图像说明


你能添加一下代码,展示你是如何分配搜索栏的吗? - Ganesh Somani
1
请查看这篇文章。 - MendyK
我已经尝试过使用这段代码,但在iOS 8上无法工作。 - Fabio
16个回答

45

我认为没有简单的方法来连接X按钮。

然而,您可以连接它的直接结果:清除文本。

尝试这个:

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText == "" {
        print("UISearchBar.text cleared!")
    }
}
副作用是当您手动清除文本时,它也会被调用。

8
更准确的描述是,使用这种方法来检测清除按钮的按下是一种hack手段。我简直无法相信在这么多年之后,苹果还没有解决这个问题。 - funct7
如果不起作用,添加下划线应该可以解决。即:(_ searchBar: UISearchBar, textDidChange searchText: String) - Emil
使用这种方法,您无法区分使用键盘删除文本和按下x按钮的操作。 - lolelo

21

这种方法有些糟糕,但是它可以工作。

private var didTapDeleteKey = false

func searchBar(_ searchBar: UISearchBar,
               shouldChangeTextIn range: NSRange,
               replacementText text: String) -> Bool
{
    didTapDeleteKey = text.isEmpty

    return true
}

func searchBar(_ searchBar: UISearchBar,
               textDidChange searchText: String)
{
    if !didTapDeleteKey && searchText.isEmpty {
        // Do something here
    }

    didTapDeleteKey = false
}

这段代码的成功关键在于,当点击搜索栏的清除按钮时,不会调用searchBar(_:shouldChangeTextIn:replacementText:) -> Bool 方法。相反,当键盘的删除按钮被点击时,该方法会被调用。


1
黑客?苹果从未意识到人们想要点击那个X? - Duck
当按下X键时,shouldChangeTextIn方法不会被调用。 - Peter Lapisu

20

Swift 5.2,Xcode 11.4

这个方法对我有效。

if let searchTextField = self.categoriesSearchBar.value(forKey: "searchField") as? UITextField , let clearButton = searchTextField.value(forKey: "_clearButton")as? UIButton {

     clearButton.addTarget(self, action: #selector(self.yourFunction), for: .touchUpInside)
}

这段代码应该在哪里使用?我已经试了好几天想清空文本字段! - Guilherme Crozariol
@GuilhermeCrozariol,你可以将这段代码放在任何地方,例如viewDidLoad()等。 - Kedar Sukerkar
2
如果苹果将来决定更改此键,这将依赖于keypath“_clearButton”,则此操作将停止工作。 - abhinavroy23
是的... 到那时也许就可以直接暴露按钮属性了。 - Kedar Sukerkar
2
这一定是最好的答案!谢谢Kedar - Vinayak Bhor

10

Apple 文档 所述,UITextFieldDelegate 中有一个委托方法 textFieldShouldClear(_:)

当用户按下内置的“清除”按钮时,文本字段会调用此方法。

因此

  1. 遵循 UITextFieldDelegate 协议
  2. 设置您的 searchBar 的文本字段的代理
  3. 实现 textFieldShouldClear(_:) 方法
class MyClass: UITextFieldDelegate {
   weak var seachBar: UISearchBar!

   override func viewDidLoad() {
       if #available(iOS 13.0, *) {
          searchBar.searchTextField.delegate = self
       } else {
          searchBar.textField.delegate = self
       }
   }

   func textFieldShouldClear(_ textField: UITextField) -> Bool {
        // your code
        return true
    }
}

这 (!!) 应该是被接受的答案。 - Soberman

9

Swift 5.0 中的最简单解决方案:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            searchBar.resignFirstResponder()
        }
    }
}

阅读标题中的文档... - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText; // 当文本发生变化(包括清除)时调用 - zumzum

4
我遇到了同样的问题,解决方法如下: 在继承自UISearchController的搜索控制器中,我添加了对UITextFieldDelegate的遵循。 然后在init方法中添加了以下行:
searchBar.searchTextField.delegate = self

并实现

func textFieldShouldClear(_ textField: UITextField) -> Bool

允许获取清除按钮被按下的信息。


4
我遇到了相同的问题,试图通过访问searchBar的子视图textField来解决它,但导致我的应用程序崩溃,在最后的努力中,我找到了这个post
另一个问题是,当取消按钮被点击时,-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText会被调用两次,也可以参见this
最后我做的是;
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if (![searchText isEqualToString:self.searchText]) {
        self.searchText = searchText;
        return;
    }
    NSLog(@"Clear clicked");
}

这解决了我的问题。


4
self.mySearchBar.searchTextField.delegate = self

    extension myViewController: UISearchTextFieldDelegate {

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            self.mySearchBar.searchTextField.resignFirstResponder()
        }
        return true
    }
}

3

我认为这个问题最简单的解决方案是:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
     if searchText.isEmpty {
             DispatchQueue.main.async {
                 searchBar.resignFirstResponder()
             }
 }

2
这对我有效。
-(UITextField*)getUITexfieldInUISearchBar:(UIView*)aSearchBar{
UITextField *searchBarTextField;
for (UIView *subView in [aSearchBar subviews]){
    if ([subView isKindOfClass:[UITextField class]])
    {
        searchBarTextField = (UITextField *)subView;
        [searchBarTextField setDelegate:self];
        break;

    }else if ([subView isKindOfClass:[UIView class]]){
        [self getUITexfieldInUISearchBar:subView];
    }
}
  return searchBarTextField;
}

你可以使用 TextFields 代理

- (BOOL)textFieldShouldClear:(UITextField *)textField {
   //Do something here...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接