UISearchBar Отключить автоматическое отключение кнопки отмены

StackOverflow https://stackoverflow.com/questions/4348351

  •  30-09-2019
  •  | 
  •  

Вопрос

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

Я пытался получить свой список как можно ближе к функциональности приложения Apple Contaction Contaction, и когда вы нажмете поиск в этом приложении, он не отключает кнопку «Отмена».

Когда я посмотрел в файл заголовка UISearchBar, я заметил флаг для AutodisableCancelbutton под структурой _earchBarflags, но он является частным.

Есть ли что-то, что я скучаю, когда я настроил UISearchBar?

Это было полезно?

Решение

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

for (UIView *possibleButton in searchBar.subviews)
{
    if ([possibleButton isKindOfClass:[UIButton class]])
    {
        UIButton *cancelButton = (UIButton*)possibleButton;
        cancelButton.enabled = YES;
        break;
    }
}

Другие советы

Я должен был настроить это немного, чтобы поработать для меня в 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;
            }
        }
    }
}

Есть два способа достичь этого легко

- (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, и никаких изменений, а также я использую его в моем магазине, утвержденном приложении без каких-либо проблем.

Это то, что сделало его на работу на IOS 6 для меня:

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

Вот мое решение, которое работает для всех ситуаций во всех версиях 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. Но я нашел ответ.

Что я пытаюсь, это что-то вроде приложения в Твиттере IOS. Если вы нажмете на увеличительное стекло на вкладке TimeLines, 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).

enter image description here

Тогда это UIView Держит А.Н. NSArray называется subviewCache И я заметил, что последний элемент, который третий, имеет тип UINavigationButton, не в публичном API. Поэтому я установил, чтобы использовать кодирование ключа-значения вместо этого. Я проверил, если UINavigationButton отвечает setEnabled:, И, к счастью, это делает. Итак, я установил свойство в @YES. Отказ Оказывается, что UINavigationButton является кнопка отмены.

Это связано с нарушением, если Apple решит изменить реализацию 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 у меня есть следующее решение C # Работа для iOS 7 и iOS 8:

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

Этот ответ основан на Дэвид Дуглас решение.

Более полный ответ:

  • Поскольку iOS 7, существует дополнительный уровень подзвучащихся под панелью поиска
  • Хорошее место, чтобы включить кнопку Отмена в 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
        }
      })
    }
  }
}

Вот решение 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
            }
        }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top