Показать предварительно загруженные Результаты поиска?
У меня есть представление без tableview с панелью поиска в нем, и хотя оно отлично работает, контроллер отображения поиска скрывает представление таблицы и накладывает темный затемненный вид, когда пустая строка находится в строке поиска. Я хочу, чтобы он показывал предварительно загруженные данные, когда пустая строка находится в строке поиска, а не скрывал представление таблицы и накладывал темный затемненный вид под панелью поиска. Так же, как работает строка поиска Google в Safari для iOS.
Я нашел аналогичный вопрос, заданный на сайте StackOverflow, прежде чем: UISearchDisplayController-как предварительно загрузить searchResultTableView, я действительно не мог заставить его работать.
У меня нет проблем с получением предварительно загруженных данных и установкой текущих данных в него, но я не уверен, как предотвратить displaycontroller от удаления searchResultsTableView.
Заранее благодарю.
7 ответов:
Я наконец-то нашел способ сделать это.
Я обнаружил, что searchDisplayController просто удаляет searchResultsTableView из супервизора, поэтому я просто добавил табличное представление обратно в супервизор всякий раз, когда контроллер дисплея пытался скрыть табличное представление:
- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { // add the tableview back in [self.view addSubview:self.searchDisplayController.searchResultsTableView]; }
И затем я также должен показать tableview при первом щелчке панели поиска, поэтому я сделал:
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller { // after the data has been preloaded self.searchResults = self.allItems; [self.searchDisplayController.searchResultsTableView reloadData]; } - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { [self.view addSubview:self.searchDisplayController.searchResultsTableView]; }
Для меня "allItems" - это место, где я храню все доступные для поиска элементы, а "searchResults" - это место, где отфильтрованные элементы (после поиска) сохраняются. И, конечно, вам придется предварительно загрузить элементы (например, историю поиска) перед перезагрузкой данных.
Я не знаю, является ли это хорошим способом или нет, чтобы сделать это с точки зрения производительности и что нет, но это сработало идеально для меня, и я надеюсь, что это может быть полезно и для других людей. Пожалуйста, прокомментируйте, если есть лучший способ сделать это.
После нескольких часов я, наконец, нашел решение, которое работает в iOS 7
Просто реализуйте следующие два метода в вашем UISearchDisplayDelegate
-(void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { // We need to prevent the resultsTable from hiding if the search is still active if (self.searchDisplayController.active == YES) { tableView.hidden = NO; } }
Когда начинается поиск, searchResultsTableView автоматически скрывается, поэтому нам нужно снова отобразить его
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { controller.searchResultsTableView.hidden = NO; // Then we need to remove the semi transparent overlay which is here for (UIView *v in [[[controller.searchResultsTableView superview] superview] subviews]) { if (v.frame.origin.y == 64) { [v setHidden:YES]; } } }
Я нашел гораздо лучшее решение этой проблемы, и оно, кажется, отлично работает на iOS 6 и 7. Хотя это все еще Хак,его гораздо чище и будущее доказательство Хак, чем выше. Другие решения не работают последовательно и предотвращают запуск некоторых методов UISearchDisplayDelegate! Кроме того, у меня были сложные проблемы с установкой, которые я не мог решить с помощью вышеуказанных методов. Главная проблема с другими решениями заключается в том, что они серьезно путают внутренние части системы. UISearchDisplayController. Мое решение основано на наблюдении, что UISearchDisplayContoller является UISearchbarDelegate и что автоматическое снятие и отображение таблицы результатов может быть вызвано имитацией нажатия клавиши в поле поиска! Итак:
- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { if ([controller respondsToSelector: @selector(searchBar:textDidChange:)]) [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "]; }
Этот код является будущим доказательством против сбоя, проверяя, что он отвечает на метод UISearchbarDelegate, и посылает пробел @"", чтобы обмануть UISearchDisplayController, думая, что пользователь набрал письмо.
Теперь, если пользователь набирает что-то, а затем стирает, стол снова потускнеет. Другие решения пытаются обойти это, делая что-то в методе searchDisplayController:didHideSearchResultsTableView:. Но это не имеет смысла для меня, так как, конечно, когда вы отмените поиск, он должен будет действительно скрыть таблицу результатов, и вам, возможно, потребуется запустить код в этом случае. Мое решение для этой части состоит в подклассе (обратите внимание, что вы, вероятно, можете использовать метод Swizzled Category, чтобы заставить его работать везде, если это необходимо в вашем проект):
// privately declare protocol to suppress compiler warning @interface UISearchDisplayController (Super) <UISearchBarDelegate> @end // subclass to change behavior @interface GMSearchDisplayController : UISearchDisplayController @end @implementation GMSearchDisplayController - (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchString { if (searchString.length == 0) searchString = @" "; if ([super respondsToSelector: @selector(searchBar:textDidChange:)]) [super searchBar: searchBar textDidChange: searchString]; } @end
Этот код работает путем перехвата метода делегата textDidChange и изменения нулевых или пустых строк в пробел string @"", предотвращая обычное скрытие / затемнение, которое происходит в пустой строке поиска. Если вы используете этот второй бит кода, то вы можете изменить Первый БИТ, чтобы передать ноль вместо@"", поскольку этот второй бит сделает необходимое преобразование в @" " для вас.
В моем собственном проекте мне нужно было обработать случай, когда пользователь вводит пробел, поэтому вместо этого из @" " выше я использовал определенный токен:
// arbitrary token used internally #define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_"
И затем обработайте его внутренне, преобразовав его обратно в нулевую строку:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL]) searchString = nil; }
Наслаждайтесь! :)
Это работает в iOS 8:
- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { self.searchDisplayController.searchResultsTableView.hidden = NO; } - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { self.searchDisplayController.searchResultsTableView.hidden = NO; [self.searchDisplayController.searchResultsTableView.superview.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView.superview]; CGRect frame = self.searchDisplayController.searchResultsTableView.frame; self.searchDisplayController.searchResultsTableView.frame = CGRectMake(frame.origin.x, 64, frame.size.width, frame.size.height); }
Когда вы начинаете поиск, этот метод вызывается. Добавьте searchResultsTableView и откройте его. Затем он будет отображать ваши уже загруженные данные. Я должен предварительно загрузить ваши данные, чтобы это сработало.
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; controller.searchResultsTableView.hidden = NO; } -(void) searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; controller.searchResultsTableView.hidden = NO; } -(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller { controller.searchResultsTableView.hidden = YES; }
Рабочий код IOS 9.
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { // Bring the search table view to the view's front self.searchDisplayController.searchResultsTableView.hidden = NO; [self.searchDisplayController.searchResultsTableView.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView]; } - (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { // We need to prevent the resultsTable from hiding if the search is still active if (self.searchDisplayController.active == YES) { tableView.hidden = NO; } }
Swift 2.0 + версия
func searchDisplayControllerDidBeginSearch(controller: UISearchDisplayController) { controller.searchResultsTableView.hidden = false controller.searchResultsTableView.superview!.bringSubviewToFront(controller.searchResultsTableView) } func searchDisplayController(controller: UISearchDisplayController, didHideSearchResultsTableView tableView: UITableView) { if ((searchDisplayController?.active) != nil) { tableView.hidden = false } }