11

У меня есть вид с таблицей с таблицей поиска, и в то время как он отлично работает, контроллер отображения поиска скрывает представление таблицы и накладывает темный тусклый вид, когда пустая строка находится в панели поиска. Я хочу, чтобы он показывал предварительно загруженные данные, когда пустая строка находится в поисковой панели, а не скрывает вид таблицы и накладывает темный тусклый вид под панель поиска. Так же, как работает панель поиска Google в Safari для iOS.Показать предварительные результаты поиска?

Я нашел аналогичный вопрос, заданный в stackoverflow перед: UISearchDisplayController - how to preload searchResultTableView, я не мог заставить его работать.

У меня нет проблем с получением предварительно загруженных данных и установкой текущих данных на него, но я не уверен, как предотвратить удаление диспетчера дисплея из поискаResultsTableView.

Заранее спасибо.

ответ

13

Наконец-то я нашел способ сделать это.

я узнал, что searchDisplayController просто удаляет searchResultsTableView из надтаблицы, так что я просто добавил вид таблицы обратно в надтаблицы всякий раз, когда контроллер дисплея пытался скрыть вид таблицы:

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView 
{ 
    // add the tableview back in 
    [self.view addSubview:self.searchDisplayController.searchResultsTableView]; 
} 

, а затем я также должно показать Tableview в первый раз Searchbar щелчка, так что я сделал:

- (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» есть где отфильтрованные элементы (после поиск) сохраняются. И, конечно же, перед перезагрузкой данных вам придется предварительно загружать элементы (например, историю поиска).

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

+0

большой материал, спасибо за этот – NSTJ

+0

пытался выяснить это в течение нескольких дней сейчас Спасибо за решение! –

+1

После тестирования этой реализации теперь я хочу выяснить, как заставить контейнер результатов поиска не мерцать, когда он добавляется в представление. Поскольку он добавлен с помощью метода searchDisplayControllerDidBeginSearch:, вы можете увидеть тусклый фон за долю секунды, пока не появится «searchResultsTableView». Любые мысли о том, как обойти это? Я попытался переместить строку кода в 'searchDisplayControllerDidBeginSearch' на метод' searchDisplayControllerWillBeginSearch ', но это заставляет тусклый фон размещаться перед 'searchResultsTableView' –

1

Когда вы начинаете поиск, этот метод вызывается. Добавьте 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; 
} 
4

После нескольких часов и часов я наконец поняли, решение, которое работает в прошивке 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]; 
     } 
    } 

} 
+0

Это не работало на iOS7 для меня. Вместо этого я проверил, если (v.alpha <1), похоже, самый «устойчивый» взлом. –

+0

Это сработало для меня, хорошо! –

4

Я нашел много лучшее решение этой проблемы, и, похоже, он отлично работает на 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 Категорию, чтобы заставить его работать везде, если это необходимо в вашем проекте):

// 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#_" 

А затем обрабатывать его внутри путем преобразования его назад до нулевой строки:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{ 
    if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL]) 
     searchString = nil; 
} 

Наслаждайтесь! :)

2

Это работает прошивкой 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); 
} 
0

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; 
    } 
} 
0

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