IOS8 Не удается скрыть кнопку отмены на панели поиска в UISearchController
Моя цель - не допустить появления кнопки отмены в строке поиска в UISearchController. Я начал с Поиск Apple Table с кодом примера UISearchController и спрятал кнопку отмены, как показано в нижеприведенной ссылке. Однако, когда пользователь вступает в текстовое поле, кнопка отмены все еще появляется. Любая помощь?
override func viewDidLoad() {
super.viewDidLoad()
resultsTableController = ResultsTableController()
searchController = UISearchController(searchResultsController: resultsTableController)
searchController.searchResultsUpdater = self
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
searchController.searchBar.delegate = self
//Hide cancel button - added by me
searchController.searchBar.showsCancelButton = false
...
Ответы
Ответ 1
Я думаю, что есть три способа достичь этого:
- Переопределить searchDisplayControllerDidBeginSearch и использовать следующий код:
searchController.searchBar.showsCancelButton = false
-
Подкласс UISearchBar и переопределить layoutSubviews для изменения этого var, когда система пытается его нарисовать.
-
Зарегистрируйтесь для уведомления клавиатуры UIKeyboardWillShowNotification и примените код в точке 1.
Конечно, вы всегда можете реализовать свою панель поиска.
Ответ 2
Для iOS 8 и UISearchController используйте этот метод делегата из UISearchControllerDelegate
:
func didPresentSearchController(searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
Не забудьте указать себя как делегата: searchController.delegate = self
Ответ 3
Просто подкласс UISearchController
и UISearchBar
.
class NoCancelButtonSearchController: UISearchController {
let noCancelButtonSearchBar = NoCancelButtonSearchBar()
override var searchBar: UISearchBar { return noCancelButtonSearchBar }
}
class NoCancelButtonSearchBar: UISearchBar {
override func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) { /* void */ }
}
Ответ 4
Следующие подпроекты проекта github UISearchBar, которые представлены как решение 2:
https://github.com/mechaman/CustomSearchControllerSwift
Кроме того, он также подклассифицирует UISearchController, чтобы включить отображение строки поиска в местах, отличных от заголовка tableView!
Надеюсь, что это поможет.
Ответ 5
Это было самое простое решение, которое я мог придумать в Swift.
Пользовательский контроллер поиска:
class CustomSearchController: UISearchController {
var _searchBar: CustomSearchBar
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
self._searchBar = CustomSearchBar()
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
override init(searchResultsController: UIViewController?) {
self._searchBar = CustomSearchBar()
super.init(searchResultsController: searchResultsController)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var searchBar: UISearchBar {
return self._searchBar
}
}
Панель пользовательского поиска:
class CustomSearchBar: UISearchBar {
override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
// do nothing
}
}
Наиболее важной частью этого было создание только объекта _searchBar
один раз в init
против его создания внутри хранимого свойства.
Ответ 6
TL; DR:
Подкласс UISearchBar
и переопределение setShowsCancelButton:
и setShowsCancelButton:animated:
скрывает кнопку отмены.
РЕШЕНИЕ
Я установил active
в NO
, если строка поиска не является первым ответчиком (клавиатура не активна и не отображается), так как это фактически команда отмены.
FJSearchBar
Маркировка searchController.searchBar.showsCancelButton = NO
, похоже, не работает в iOS 8. Я не тестировал iOS 9.
FJSearchBar.h
Пусто, но размещена здесь для полноты.
@import UIKit;
@interface FJSearchBar : UISearchBar
@end
FJSearchBar.m
#import "FJSearchBar.h"
@implementation FJSearchBar
- (void)setShowsCancelButton:(BOOL)showsCancelButton {
// do nothing
}
- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated {
// do nothing
}
@end
FJSearchController
Здесь вы хотите внести реальные изменения. Я разделил UISearchBarDelegate
на свою собственную категорию, потому что, IMHO, категории делают классы более чистыми и удобными в обслуживании. Если вы хотите сохранить делегат в интерфейсе/реализации основного класса, вы более чем можете это сделать.
FJSearchController.h
@import UIKit;
@interface FJSearchController : UISearchController
@end
@interface FJSearchController (UISearchBarDelegate) <UISearchBarDelegate>
@end
FJSearchController.m
#import "FJSearchController.h"
#import "FJSearchBar.h"
@implementation FJSearchController {
@private
FJSearchBar *_searchBar;
BOOL _clearedOutside;
}
- (UISearchBar *)searchBar {
if (_searchBar == nil) {
// if you're not hiding the cancel button, simply uncomment the line below and delete the FJSearchBar alloc/init
// _searchBar = [[UISearchBar alloc] init];
_searchBar = [[FJSearchBar alloc] init];
_searchBar.delegate = self;
}
return _searchBar;
}
@end
@implementation FJSearchController (UISearchBarDelegate)
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
// if we cleared from outside then we should not allow any new editing
BOOL shouldAllowEditing = !_clearedOutside;
_clearedOutside = NO;
return shouldAllowEditing;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
// hide the keyboard since the user will no longer add any more input
[searchBar resignFirstResponder];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (![searchBar isFirstResponder]) {
// the user cleared the search while not in typing mode, so we should deactivate searching
self.active = NO;
_clearedOutside = YES;
return;
}
// update the search results
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
}
@end
Некоторые примечания:
- Я положил строку поиска и
BOOL
как частные переменные вместо свойств, потому что
- Они более легкие, чем частные.
- Им не нужно видеть или изменять внешний мир.
- Мы проверяем, является ли
searchBar
первым ответчиком. Если это не так, мы фактически деактивируем контроллер поиска, потому что текст пуст, и мы больше не ищем. Если вы уверены, что действительно, вы также можете убедиться, что searchText.length == 0
.
-
searchBar:textDidChange:
вызывается перед searchBarShouldBeginEditing:
, поэтому мы обработали его в этом порядке.
- Я обновляю результаты поиска каждый раз, когда текст изменяется, но вы можете переместить
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
в searchBarSearchButtonClicked:
, если вы хотите, чтобы поиск выполнялся после нажатия пользователем кнопки поиска.
Ответ 7
Использовать UISearchControllerDelegate.
func willPresentSearchController(_ searchController: UISearchController) {
searchController.searchBar.setValue("", forKey:"_cancelButtonText")
}
Ответ 8
Просто подклассифицируйте свой UISearchController и выполните следующие действия:
class CustomSearchController: UISearchController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
searchBar.showsCancelButton = false
}
}
Это было самое простое решение, которое я мог придумать, чтобы решить проблему с мигающей кнопкой отмены.