Показать предварительные результаты поиска?

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