2010-12-03 5 views
36

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

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

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

Есть ли что-то, что мне не хватает при настройке UISearchBar?

ответ

51

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

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

Это не работает для меня на прошивке 6, так как единственной кнопкой является UINavigationButton, который выглядит как частный класс. – 2012-10-25 23:41:39

+1

Вы пытались установить свойство showCancelButton на UISearchBar? – rplankenhorn 2012-10-26 14:32:37

+2

UINavigationButton является подклассом, если UIButton, поэтому этот код работает, и нет использования частного класса. https://github.com/kennytm/iphone-private-frameworks/blob/master/UIKit/UINavigationButton.h – Mitya 2013-01-10 14:34:57

3

Это то, что сделал это, чтобы работать на IOS 6 для меня:

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

это не решает проблему: оператору требуется отключить функцию автоматического отключения, то есть не разрешать UISearchBar ее отключать. – dwery 2013-07-16 22:11:42

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; 
      } 
     } 
    } 
} 
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]; 
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).

enter image description here

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

Это обязательно сломается, если Apple решит изменить реализацию внутренних дел, но какого черта. Сейчас это работает.

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

Для MonoTouch или Xamarin прошивки у меня есть следующее C# решение работает прошивка 7 и прошивка 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; 
      } 
     } 
    } 
} 

Этого ответ основано на решении David Douglas.

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 изменит его в фоновом режиме.

BTW Я протестировал его с iOS 4.0 до 8.2 и никаких изменений, также я использую его в своем приложении, одобренном в Магазине, без каких-либо проблем.

1

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

  • так прошивкой 7, есть дополнительный уровень подвидов под SearchBar
  • хорошее место, чтобы включить кнопку отмены в 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 
     } 
     }) 
    } 
    } 
} 
1

Вот 3 решения Swift, что делает использование расширений, чтобы получить кнопку отмены легко:

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 
      } 
     } 
    } 
} 
Смежные вопросы