我可以钩入UISearchBar的清除button吗?
我的界面中有一个UISearchBar,我想定制一些文本input后出现在search栏中的小清除button的行为(这是一个带有十字的小灰圈,出现在右边search栏的旁边)。
基本上,我希望它不仅清除search栏的文本(这是默认的实现),而且还清除我的界面的其他东西,但调用我自己的方法之一。
我找不到UISearchBar类或UISearchBarDelegate协议的文档中的任何内容 – 它看起来不像你可以直接访问这种行为。
我注意到的一件事就是文档解释了委托方法:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
在清除button被点击之后被调用。
我最初编写了一些代码,检查search栏的文本属性,如果它是空的,那么它已被清除,并做我所有的其他东西。
这个虽然有两个问题:
首先,由于某种原因,我无法理解,即使我告诉search栏resignFirstResponder在我的方法结束,某处,将其设置回成为FirstResponder。 真的很烦人
其次,如果用户没有使用清除button,只需用键盘上的删除button删除栏中的文本,就会触发该方法,其search结果将消失。 不好。
任何意见或指针在正确的方向将是伟大的!
谢谢!
被接受的答案是不正确的。 这可以做,我只是想出来,并张贴在另一个问题:
UISearchbar clearButton强制显示键盘
最好
find这个问题的更好的解决scheme:)
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{ if ([searchText length] == 0) { [self performSelector:@selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0]; } } - (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar{ [searchBar resignFirstResponder]; }
我在我的应用程序中有这个代码。 不同的是,我不支持“实时search”,而是在用户触摸键盘上的searchbutton时开始search:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { if ([searchBar.text isEqualToString:@""]) { //Clear stuff here } }
Swift版本处理closures键盘清除button点击:
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { if searchText.characters.count == 0 { performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0) } } func hideKeyboardWithSearchBar(bar:UISearchBar) { bar.resignFirstResponder() }
我会build议使用UITextField的rightView
和rightViewMode
方法来创build自己的清除button,使用相同的图像。 我假设当然,UISearchBar会让你访问它内的UITextField。 我想会的。
从iPhone OS参考资料库中了解这一点:
If an overlay view overlaps the clear button, however, the clear button always takes precedence in receiving events. By default, the right overlay view does overlap the clear button.
所以你可能还需要禁用原来的清除button。
由于这首先出现,而且我可以看到这个问题没有得到充分的解决,我想我会发布我的解决scheme。
1)你需要在searchBar中获得对textField的引用2)你需要捕获textField在被触发时清除。
这很简单。 这是一种方法。
一)确保你让你的类,因为你将使用searchBar内的textField的委托方法。 b)另外,将你的searchBar连接到你的课堂上的Outlet。 我只是叫我的search栏。 c)从viewDidLoad中,你要获得searchBar里面的textField的位置。 我是这样做的。
UITextField *textField = [self.searchBar valueForKey:@"_searchField"]; if (textField) { textField.delegate = self; textField.tag = 1000; }
请注意,我为该textField分配了一个标签,以便我可以再次抓取它,并将其作为textField委托。 您可能已经创build了一个属性,并将该textField分配给该属性以便稍后抓取它,但是我使用了一个标记。
从这里你只需要调用委托方法:
-(BOOL)textFieldShouldClear:(UITextField *)textField { if (textField.tag == 1000) { // do something return YES; } return NO;
}
而已。 既然你指的是一个私有的valueForKey,我不能保证它不会让你陷入困境。
你可以试试这个:
- (void)viewDidLoad { [super viewDidLoad]; for (UIView *view in searchBar.subviews){ for (UITextField *tf in view.subviews) { if ([tf isKindOfClass: [UITextField class]]) { tf.delegate = self; break; } } } } - (BOOL)textFieldShouldClear:(UITextField *)textField { // your code return YES; }
从我的经验来看,最好的解决办法就是在系统清除button的上方放一个UIButton(背景清晰,没有文字),然后连接一个IBAction
- (IBAction)searchCancelButtonPressed:(id)sender { [self.searchBar resignFirstResponder]; self.searchBar.text = @""; // some of my stuff self.model.fastSearchText = nil; [self.model fetchData]; [self reloadTableViewAnimated:NO]; }
在这里找不到一个没有使用私有API的解决scheme,或者没有升级certificate,苹果改变了UISearchBar的视图结构。 这是我写的那个作品:
- (void)viewDidLoad { [super viewDidLoad]; UITextField* textfield = [self findTextFieldInside:self.searchBar]; [textfield setDelegate:self]; } - (UITextField*)findTextFieldInside:(id)mainView { for (id view in [mainView subviews]) { if ([view isKindOfClass:[UITextField class]]) { return view; } id subview = [self findTextFieldInside:view]; if (subview != nil) { return subview; } } return nil; }
然后在您的类中实现UITextFieldDelegate协议并覆盖textFieldShouldClear:方法。
- (BOOL)textFieldShouldClear:(UITextField*)textField { // Put your code in here. return YES; }
编辑:在iOS8的search栏的文本框中设置代理将导致崩溃。 然而,它看起来像searchBar:textDidChange:方法将清除iOS8上调用。