Показать предварительные результаты поиска?
У меня есть представление, отличное от таблицы, с поисковой панелью в нем, и, хотя он отлично работает, контроллер отображения поиска скрывает представление таблицы и накладывает темное тусклое представление, когда пустая строка находится в панели поиска. Я хочу, чтобы он показывал предварительно загруженные данные, когда пустая строка находится в поисковой панели, а не скрывает вид таблицы и накладывает темный тусклый вид под панель поиска. Так же, как работает панель поиска Google в Safari для iOS.
Я нашел аналогичный вопрос, заданный в stackoverflow:
UISearchDisplayController - как предварительно загрузить searchResultTableView, я не мог заставить его работать.
У меня нет проблем с получением предварительно загруженных данных и установкой текущих данных, но я не уверен, как предотвратить удаление диспетчера дисплея из поискаResultsTableView.
Спасибо заранее.
Ответы
Ответ 1
Наконец-то я нашел способ сделать это.
Я выяснил, что 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" - это место, где хранятся отфильтрованные элементы (после поиска). И, конечно же, перед перезагрузкой данных вам придется предварительно загружать элементы (например, историю поиска).
Я не знаю, хорошо это или нет, с точки зрения производительности, а что нет, но он отлично работал у меня, и я надеюсь, что это может быть полезно и для других людей. Прошу прокомментировать, если есть лучший способ сделать это.
Ответ 2
Через несколько часов я наконец выяснил решение, которое работает в 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];
}
}
}
Ответ 3
Я нашел решение гораздо лучше для этой проблемы, и, похоже, он отлично работает на 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, и отправляет space @"", чтобы обмануть 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 и изменяя нулевые или пустые строки в строку пробела @ ", предотвращая нормальное скрытие/затемнение, которое происходит на пустой строке поиска. Если вы используете этот второй бит кода, вы можете изменить первый бит, чтобы передать нуль вместо @", поскольку этот второй бит выполнит необходимое преобразование в @ "" для вас.
В моем собственном проекте мне нужно было обработать случай, когда пользователь вводит пробел, поэтому вместо @"" выше я использовал определенный токен:
// arbitrary token used internally
#define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_"
И затем обработайте его внутренне, переведя его обратно в строку nil:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL])
searchString = nil;
}
Наслаждайтесь!:)
Ответ 4
Это работает в 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);
}
Ответ 5
Когда вы начинаете поиск, этот метод вызывается. Добавьте 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;
}
Ответ 6
рабочий код iOS 9.
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
// Bring the search table view to the view 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;
}
}
Ответ 7
версия 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
}
}