我已经将UISearchBar实现到一个表视图中,除了一件小事之外几乎所有东西都在工作:当我输入文本然后按键盘上的搜索按钮时,键盘消失,搜索结果是显示的唯一项目在表中,文本保留在UISearchBar中,但取消按钮被禁用。
我一直试图让我的列表接近Apple联系人应用程序的功能,当您在该应用程序中按搜索时,它不会禁用取消按钮。
当我查看UISearchBar头文件时,我注意到_searchBarFlags结构下的autoDisableCancelButton标志,但它是私有的。
设置UISearchBar时是否存在我遗漏的内容?
答案 0 :(得分:51)
我找到了解决方案。您可以使用此for循环遍历搜索栏的子视图,并在键盘上按下搜索按钮时启用它。
for (UIView *possibleButton in searchBar.subviews)
{
if ([possibleButton isKindOfClass:[UIButton class]])
{
UIButton *cancelButton = (UIButton*)possibleButton;
cancelButton.enabled = YES;
break;
}
}
答案 1 :(得分:15)
我必须稍微调整一下才能让它在iOS7中适用于我
- (void)enableCancelButton:(UISearchBar *)searchBar
{
for (UIView *view in searchBar.subviews)
{
for (id subview in view.subviews)
{
if ( [subview isKindOfClass:[UIButton class]] )
{
[subview setEnabled:YES];
NSLog(@"enableCancelButton");
return;
}
}
}
}
答案 2 :(得分:5)
有两种方法可以轻松实现这一目标
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
// The small and dirty
[(UIButton*)[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
// The long and safe
UIButton *cancelButton = [searchBar valueForKey:@"_cancelButton"];
if ([cancelButton respondsToSelector:@selector(setEnabled:)]) {
cancelButton.enabled = YES;
}
}
你应该使用第二个,如果Apple将在后台更改它,它不会使你的应用程序崩溃。
顺便说一句,我测试它从iOS 4.0到8.2并且没有任何变化,我也在我的商店批准的应用程序中使用它而没有任何问题。
答案 3 :(得分:3)
这就是让我在iOS 6上工作的原因:
searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];
答案 4 :(得分:3)
这是我的解决方案,适用于所有iOS版本的所有情况。
IE,其他解决方案在键盘被解除时无法处理,因为用户拖动了滚动视图。
- (void)enableCancelButton:(UIView *)view {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view setEnabled:YES];
} else {
for (UIView *subview in view.subviews) {
[self enableCancelButton:subview];
}
}
}
// This will handle whenever the text field is resigned non-programatically
// (IE, because it's set to resign when the scroll view is dragged in your storyboard.)
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[self performSelector:@selector(enableCancelButton:) withObject:searchBar afterDelay:0.001];
}
// Also follow up every [searchBar resignFirstResponder];
// with [self enableCancelButton:searchBar];
答案 5 :(得分:2)
这些答案根本不适用于我。我的目标是iOS 7.但我找到了答案。
我正在尝试的是像Twitter iOS应用程序。如果单击时间轴选项卡中的放大镜,则会显示UISearchBar
,其中激活取消按钮,键盘显示和最近搜索屏幕。滚动最近的搜索屏幕,它会隐藏键盘,但它会激活取消按钮。
这是我的工作代码:
UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
[subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}
我通过在我的表视图scrollViewWillBeginDragging:
设置断点来实现此解决方案。我查看了我的UISearchBar
并露出了它的子视图。它总是只有一个,类型UIView
(我的变量searchBarSubview
)。
然后,UIView
持有名为NSArray
的{{1}},我注意到最后一个元素是第三个属于subviewCache
类型,而不是公开API。所以我开始使用键值编码。我检查UINavigationButton
是否响应UINavigationButton
,幸运的是,确实如此。所以我将属性设置为setEnabled:
。事实证明,@YES
是取消按钮。
如果Apple决定改变UINavigationButton
内部的实施,这肯定会破裂,但到底是什么。它现在有效。
答案 6 :(得分:2)
根据my answer here,将其放在searchBar委托中:
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
dispatch_async(dispatch_get_main_queue(), ^{
__block __weak void (^weakEnsureCancelButtonRemainsEnabled)(UIView *);
void (^ensureCancelButtonRemainsEnabled)(UIView *);
weakEnsureCancelButtonRemainsEnabled = ensureCancelButtonRemainsEnabled = ^(UIView *view) {
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UIControl class]]) {
[(UIControl *)subview setEnabled:YES];
}
weakEnsureCancelButtonRemainsEnabled(subview);
}
};
ensureCancelButtonRemainsEnabled(searchBar);
});
}
答案 7 :(得分:1)
对于Monotouch或Xamarin iOS,我有以下适用于iOS 7和iOS 8的C#解决方案:
foreach(UIView view in searchBar.Subviews)
{
foreach(var subview in view.Subviews)
{
//Console.WriteLine(subview.GetType());
if(subview.GetType() == typeof(UIButton))
{
if(subview.RespondsToSelector(new Selector("setEnabled:")))
{
UIButton cancelButton = (UIButton)subview;
cancelButton.Enabled = true;
Console.WriteLine("enabledCancelButton");
return;
}
}
}
}
此答案基于David Douglas解决方案。
答案 8 :(得分:1)
更完整的答案:
searchBarTextDidEndEditing
extension MyController: UISearchBarDelegate {
public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
DispatchQueue.main.async {
// you need that since the disabling will
// happen after searchBarTextDidEndEditing is called
searchBar.subviews.forEach({ view in
view.subviews.forEach({ subview in
// ios 7+
if let cancelButton = subview as? UIButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
return
}
})
// ios 7-
if let cancelButton = subview as? UIButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
return
}
})
}
}
}
答案 9 :(得分:1)
这是一个Swift 3解决方案,它使用扩展来轻松获取取消按钮:
extension UISearchBar {
var cancelButton: UIButton? {
for subView1 in subviews {
for subView2 in subView1.subviews {
if let cancelButton = subView2 as? UIButton {
return cancelButton
}
}
}
return nil
}
}
现在用于:
class MyTableViewController : UITableViewController, UISearchBarDelegate {
var searchBar = UISearchBar()
func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
tableView.tableHeaderView = searchBar
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
DispatchQueue.main.async {
if let cancelButton = searchBar.cancelButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
}
}
}
}
答案 10 :(得分:0)
时间流逝,但问题仍然存在...
优雅的 Swift 5 / iOS 13 解决方案:
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
for case let cancelButton as UIButton in searchBar.subviews {
cancelButton.isEnabled = true
}
}