Ios4 UI搜索栏禁用自动禁用取消按钮

Ios4 UI搜索栏禁用自动禁用取消按钮,ios4,uisearchbar,cancel-button,Ios4,Uisearchbar,Cancel Button,我在表视图中实现了一个UISearchBar,除了一件小事之外,几乎所有的东西都在工作:当我输入文本,然后按下键盘上的搜索按钮时,键盘消失,搜索结果是表中显示的唯一项目,文本保留在UISearchBar中,但取消按钮被禁用 我一直试图让我的列表尽可能接近Apple contacts应用程序的功能,当你在该应用程序中按search时,它不会禁用cancel按钮 当我查看UISearchBar头文件时,我注意到在_searchBarFlags结构下有一个autoDisableCancelButton

我在表视图中实现了一个UISearchBar,除了一件小事之外,几乎所有的东西都在工作:当我输入文本,然后按下键盘上的搜索按钮时,键盘消失,搜索结果是表中显示的唯一项目,文本保留在UISearchBar中,但取消按钮被禁用

我一直试图让我的列表尽可能接近Apple contacts应用程序的功能,当你在该应用程序中按search时,它不会禁用cancel按钮

当我查看UISearchBar头文件时,我注意到在_searchBarFlags结构下有一个autoDisableCancelButton标志,但它是私有的


当我设置UISearchBar时,是否有遗漏的内容?

我找到了解决方案。您可以使用此for循环在搜索栏的子视图上循环,并在按下键盘上的搜索按钮时启用它

for(UIView*搜索栏中的可能按钮。子视图)
{
if([possibleButton IsKindof类:[UIButton类]])
{
UIButton*cancelButton=(UIButton*)可能的按钮;
cancelButton.enabled=是;
打破
}
}

这就是我在iOS 6上工作的原因:

searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];

为了让它在iOS7中为我工作,我不得不对它进行一些调整

-(void)enableCancelButton:(UISearchBar*)搜索栏
{
用于(UIView*搜索栏中的视图。子视图)
{
用于(视图中的id子视图。子视图)
{
if([subview iskindof类:[UIButton类]])
{
[子视图设置启用:是];
NSLog(@“启用取消按钮”);
返回;
}
}
}
}

这是我的解决方案,它适用于所有版本的iOS中的所有情况

也就是说,由于用户拖动了一个滚动视图,所以当键盘被关闭时,其他解决方案无法处理

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

没有一个答案对我有用。我的目标是iOS 7。但我找到了答案

我正在尝试的是类似于Twitter iOS应用程序的东西。如果单击“时间线”选项卡中的放大镜,则会出现
ui搜索栏
,并激活“取消”按钮,显示键盘和“最近搜索”屏幕。滚动最近的搜索屏幕,它隐藏键盘,但它保持取消按钮激活

这是我的工作代码:

UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
    [subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}
我通过在表视图的
ScrollViewWillBeginDraging:
上设置断点来实现此解决方案。我查看了我的
ui搜索栏
,并显示了它的子视图。它总是只有一个,类型为
UIView
(我的变量
searchBarSubview

然后,
UIView
保存一个名为
subviewCache
NSArray
,我注意到最后一个元素,即第三个元素,是
UINavigationButton
类型,不在公共API中。所以我开始使用键值编码来代替。我检查了
UINavigationButton
是否响应
setEnabled:
,幸运的是,它响应了。因此,我将属性设置为
@YES
。原来,
UINavigationButton
是取消按钮

如果苹果决定改变
UISearchBar
的内部实现,这一点肯定会被打破,但这到底是怎么回事。现在可以使用了。

根据,将其放置在搜索栏代理中:

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

对于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;
            }
        }
    }
}

这个答案基于解决方案。

有两种方法可以轻松实现这一点

- (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;
    }
}
你应该使用第二个,如果苹果在后台更改它,它不会使你的应用程序崩溃


顺便说一句,我从iOS 4.0到8.2对它进行了测试,没有任何更改,而且我在商店认可的应用程序中使用了它,没有任何问题。

更完整的答案:

  • 自iOS 7以来,在搜索栏下增加了一级子视图
  • 启用“取消”按钮的最佳位置是
    searchbartextdidediting


下面是一个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
            }
        }
    }
}

时间流逝,但问题仍然存在

优雅的Swift 5/iOS 13解决方案:

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    for case let cancelButton as UIButton in searchBar.subviews {
        cancelButton.isEnabled = true
    }
}

这对我在iOS 6上不起作用,因为唯一存在的按钮是一个UINavigationButton,它似乎是一个私有类。您是否尝试在UISearchBar上设置showsCancelButton属性?UINavigationButton是UIButton的子类,因此此代码有效,并且没有私有类用法。在搜索栏失去焦点(辞职FirstResponder)后,你只需要在适当的时候使用它。对我来说很有用!我做了
((UIButton*)可能的按钮)。enabled=YES
我发现使用了太多的
cancelButton
。这并不能解决问题:op想要禁用自动禁用功能,即不允许UISearchBar禁用它。您应该返回内部if语句,而不是中断。该break语句只会将您从内部for循环中分离出来,并将继续在searchBar.subview上循环,即使在找到“取消”按钮后也是如此。这是可行的,但您的应用可能会被拒绝,因为它使用的是私有方法。小心。@PedroJoséCardoso不,这并不算是私有api的使用,而且我从来没有见过任何因为这一点而被拒绝的情况。这是我见过的最干净的解决方案。谢谢。在iOS 13+上不起作用,因为在iOS 13
UISearchBar中,
subview 2
不是
UIButton
。subview
只返回一个元素,而不是
UIButton
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    for case let cancelButton as UIButton in searchBar.subviews {
        cancelButton.isEnabled = true
    }
}