Как сохранить кнопку отмены в панели поиска, когда клавиатура отклоняется?

enter image description hereenter image description here

Я пытаюсь добиться такого же эффекта, как приложение Apple Contacts (левый снимок экрана). Кнопка отмены в UISearchBar включена, даже если клавиатура отклоняется. Мое приложение ведет себя по-другому (правый скриншот). Кнопка отмены автоматически отключается, когда клавиатура отклоняется. Пользователь должен нажать кнопку отмены один раз, чтобы включить его, а затем еще раз, чтобы фактически вызвать увольнение. Это не очень хороший пользовательский интерфейс. Как я всегда буду держать кнопку отмены включенной, как приложение Apple Contacts?

Технические детали:

Я не использую UISearchDisplayController из-за некоторых требований к дизайну. Это всего лишь UISearchBar с моим собственным контроллером пользовательского поиска. Кнопка отмены отображается с помощью [self.searchBar showsCancelButton:YES animated:YES]. Клавиатура отклоняется с помощью [self.searchBar resignFirstResponder].

Ответ 1

Вызов [self.searchBar resignFirstResponder] отключит кнопку отмены. Следовательно, вы всегда должны обновить кнопку отмены, чтобы включить ее после вызова.

Objective-C

[searchBar resignFirstResponder];
UIButton *cancelButton = (UIButton *)[searchBar valueForKey:@"cancelButton"];
[cancelButton setEnabled:YES];

Swift

searchBar.resignFirstResponder()
if let cancelButton = searchBar.value(forKey: "cancelButton") as? UIButton
    cancelButton.isEnabled = true
}

По моему опыту, view.endEditing(true) является проблемой. Потому что он также называется .resignFirstResponder, если внутри представления есть UITextField, который содержится в UISearchBar.

https://developer.apple.com/reference/uikit/uiview/1619630-endediting

Ответ 2

Вы можете использовать API среды выполнения для доступа к кнопке отмены.

UIButton *btnCancel = [self.searchBar valueForKey:@"_cancelButton"];
[btnCancel setEnabled:YES];

Что касается вашего вопроса, вы не можете включить кнопку отмены, когда клавиатура отклоняется, например, нет обратного вызова.

Ответ 3

Для Swift 4.0

if let cancelButton : UIButton = searchBar.value(forKey: "cancelButton") as? UIButton{
    cancelButton.isEnabled = true
}

Ответ 4

Так как iOS 7, все подчиненные UISearchBar на один уровень глубже. Это должно работать:

for (UIView *subView in searchBar.subviews) {
    for (UIView *secondLevelSubview in subView.subviews) {
        if ([view isKindOfClass:[UIButton class]]) {
           [(UIButton *)view setEnabled:YES];
        }
}

Все еще взломанный и может легко ломаться в следующей версии iOS.

Ответ 5

Вы можете сделать это:

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self enableCancelButton];
}

- (void)enableCancelButton {
    for (UIView *view in _seachBar.subviews) {
        if ([view isKindOfClass:[UIButton class]]) {
            [(UIButton *)view setEnabled:YES];
        }
    }
}

НО, это довольно хакерский метод, и я вполне уверен, что он вообще нахмурился Apple и потенциально может привести к отклонению приложения. Насколько мне известно, похоже, что нет другого способа сделать то, что вы пытаетесь сделать.

Ответ 6

Внедрите нижеуказанный метод делегата searchBarShouldEndEditing в свой код. Надеюсь, это поможет.

(BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar 
{
    [[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
    return YES;
}

Ответ 7

Здесь рекурсивное решение, которое работает для меня.

func enableButtons(_ view:UIView) { for subView in view.subviews { enableButtons(subView) } if let buttonView = view as? UIButton { buttonView.isEnabled = true } }

Ответ 8

Вот простой способ:

searchBar.resignFirstResponder()
(searchBar.value(forKey: "_cancelButton") as? UIButton)?.isEnabled = true