如何使用UISearchBar启用取消按钮?

Chr*_*her 50 iphone cancel-button uisearchbar

在iPhone上的联系人应用程序中输入搜索词,然后点击"搜索"按钮,键盘被隐藏,但取消按钮仍然启用.在我的应用程序中,当我调用resignFirstResponder时取消按钮被禁用.

任何人都知道如何在取消按钮处于启用状态的同时隐藏键盘?

我使用以下代码:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    [searchBar resignFirstResponder];
}
Run Code Online (Sandbox Code Playgroud)

键盘滑出视图,但搜索文本字段右侧的"取消"按钮被禁用,因此我无法取消搜索.联系人应用程序将取消按钮维持在启用状态.

我想也许一个解决方案是深入到searchBar对象并在实际文本字段上调用resignFirstResponder,而不是搜索栏本身.

任何输入赞赏.

Dav*_*las 29

这种方法适用于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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(在使用[_searchBar resignFirstResponder]之后,请务必在任何地方调用它.)

  • +1"for"确保在使用[_searchBar resignFirstResponder]之后随时随地调用它." (2认同)

Mal*_*ndi 21

试试这个

for(id subview in [yourSearchBar subviews])
{
    if ([subview isKindOfClass:[UIButton class]]) {
        [subview setEnabled:YES];
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*rný 10

当您开始滚动表而不是点击"搜索"按钮时,接受的解决方案将不起作用.在这种情况下,"取消"按钮将被禁用.

这是我的解决方案,每次使用KVO禁用时,重新启用"取消"按钮.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Search for Cancel button in searchbar, enable it and add key-value observer.
    for (id subview in [self.searchBar subviews]) {
        if ([subview isKindOfClass:[UIButton class]]) {
            [subview setEnabled:YES];
            [subview addObserver:self forKeyPath:@"enabled" options:NSKeyValueObservingOptionNew context:nil];
        }
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    // Remove observer for the Cancel button in searchBar.
    for (id subview in [self.searchBar subviews]) {
        if ([subview isKindOfClass:[UIButton class]])
            [subview removeObserver:self forKeyPath:@"enabled"];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // Re-enable the Cancel button in searchBar.
    if ([object isKindOfClass:[UIButton class]] && [keyPath isEqualToString:@"enabled"]) {
        UIButton *button = object;
        if (!button.enabled)
            button.enabled = YES;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ben*_* L. 9

从iOS 6开始,该按钮似乎是UINavigationButton(私有类)而不是UIButton.

我已经调整了上面的例子看起来像这样.

for (UIView *v in searchBar.subviews) {
    if ([v isKindOfClass:[UIControl class]]) {
        ((UIControl *)v).enabled = YES;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这显然是脆弱的,因为我们正在与内部进行混杂.它还可以启用多个按钮,但它适用于我,直到找到更好的解决方案.

我们应该要求Apple揭露这一点.


小智 8

这似乎对我有用(在viewDidLoad中):

__unused UISearchDisplayController* searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
Run Code Online (Sandbox Code Playgroud)

我意识到我应该正确使用UISearchDisplayController,但这对我当前的实现来说是一个简单的修复.


Bur*_*ala 7

您可以使用运行时API来访问取消按钮.

UIButton *btnCancel = [self.searchBar valueForKey:@"_cancelButton"];
[btnCancel setEnabled:YES];
Run Code Online (Sandbox Code Playgroud)

  • 这个运行时不是访问私有 API 和应用程序拒绝的可能性吗? (2认同)
  • 最佳答案.简单快捷.非常感谢,师父. (2认同)

Bra*_*ins 5

我通过将其作为UISearchBar上的一个简单类别实现,扩展了其他人已发布的内容.

的UISearchBar + alwaysEnableCancelButton.h

#import <UIKit/UIKit.h>

@interface UISearchBar (alwaysEnableCancelButton)

@end
Run Code Online (Sandbox Code Playgroud)

的UISearchBar + alwaysEnableCancelButton.m

#import "UISearchBar+alwaysEnableCancelButton.h"

@implementation UISearchBar (alwaysEnableCancelButton)

- (BOOL)resignFirstResponder
{
    for (UIView *v in self.subviews) {
        // Force the cancel button to stay enabled
        if ([v isKindOfClass:[UIControl class]]) {
            ((UIControl *)v).enabled = YES;
        }

        // Dismiss the keyboard
        if ([v isKindOfClass:[UITextField class]]) {
            [(UITextField *)v resignFirstResponder];
        }
    }

    return YES;
}
@end
Run Code Online (Sandbox Code Playgroud)