UISearchDisplayContoller - не может предотвратить перезагрузку таблицы при наборе текста в строке поиска - PullRequest
7 голосов
/ 11 октября 2010

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

Похоже на то, чтобы настроить контроллер дисплея поиска для асинхронности, вам действительно нужно сделать две вещи:

  1. Возврат НЕТ для searchDisplayController: shouldReloadTableForSearchString, и
  2. обрабатывать searchBarSearchButtonClicked и огонь с перезагрузки стола я.

Я делаю и то, и другое, но то, что я вижу, это то, что контроллер отображения поиска перезагружает таблицу по первому символу, введенному в строку поиска, хотя я возвращаю NO согласно # 1. Он не перезагружается при вводе последующих символов.

Итак, мой вопрос: как мне удержать контроллер дисплея поиска от попытки перезагрузить таблицу, пока пользователь печатает? (специально для этого первого введенного символа)

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

Вот быстрый пример моего кода, чтобы показать проблему. Когда я запускаю это и набираю «abcde» в строке поиска, после ввода «a» результаты отображаются как «a # 0», «a # 2» и т. Д. Они не обновляются, пока я не нажму кнопку поиска. затем вы видите «abcde # 0», «abcde # 1» и т. д. Желаемый результат, конечно, ничего не происходит, пока я не нажму кнопку поиска.

#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    return NO;
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    return NO;
}


#pragma mark -
#pragma mark UISearchBarDelegate Methods

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self.searchDisplayController.searchResultsTableView reloadData];

}


#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    cell.textLabel.text = [self.searchDisplayController.searchBar.text stringByAppendingFormat:@" #%d", indexPath.row]; 
    return cell;
}

Спасибо! (кстати, это мой первый вопрос, заданный здесь - пожалуйста, дайте мне знать, если я пропущу какие-либо пункты этикета:)

Ответы [ 5 ]

15 голосов
/ 17 марта 2011

Так работает UISearchDisplayController (SDC). Когда пользователь вводит первый символ в строку поиска, таблица поиска загружается и отображается в первый раз, вызывая ее загрузку. Методы "... shouldReloadTableForSearchString" и "... shouldReloadTableForSearchScope" позволяют вам контролировать, будет ли searchTable автоматически перезагружаться при последующих символах или при изменении области.

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

Вариант 1: представить ячейку «загрузки» в таблице поиска при наборе первого символа.

Эта опция позволяет SDC отображать searchResultsTableView, когда пользователь вводит первый символ, отображать статус текущей операции поиска / фильтрации

  1. в определении класса делегата SDC

    • добавить iVar BOOL isLoading
    • добавить iVar UITableView *searchTableView
  2. в searchDisplayController:didLoadSearchResultsTableView

    • набор searchTableView = tableView
  3. в shouldReloadTableForSearchString/Scope

    • набор isLoading = YES
    • вызов вашего метода для загрузки данных в фоновом режиме
    • возврат НЕТ
  4. когда ваш фоновый фильтр завершен:

    • набор isLoading = NO
    • [searchTableView reloadData]
  5. в различных методах делегата tableView отвечают, как вы хотите показать статус, если есть текущие результаты поиска или результаты загружаются в фоновом режиме. Что я сделал, это:

    • , если есть текущие результаты поиска, показать результаты (даже если загрузка / фильтрация в фоновом режиме)
    • , если результатов поиска нет, и isLoading == NO вернуть 1 строку и показать «Нет совпадений» в ячейке
    • , если нет результатов поиска и isLoading == YES возвращают 1 строку и показывают активность поиска в ячейке (я обычно использую UIActivityIndicatorView)

Вариант 2. Скрытие searchTableView и отображение наложения в его месте до тех пор, пока не будут загружены результаты поиска

Этот параметр скрывает searchTableView при первой загрузке и только отображает его снова, когда поиск / фильтр завершены. Я определил это как дополнение к варианту 1, поскольку они могут быть выполнены вместе, хотя для оптимизации того, что вам может не понадобиться показывать поисковую активность в searchResultsTableView, если вы прячете таблицу и показываете наложение.

  1. в определении класса делегата SDC

    • аналогично варианту 1
    • добавить iVar UIView *searchTableOverlayView
  2. в searchDisplayController:didLoadSearchResultsTableView

    • так же, как вариант 1
    • создайте UIView для использования в качестве наложения вместо searchTableView, содержащего любой пользовательский интерфейс, подходящий для вашего приложения, и установите для него searchTableOverlayView
  3. в searchDisplayController:didUnloadSearchResultsTableView

    • выпуск searchTableOverlayView
  4. в 'searchDisplayController: didShowSearchResultsTableView (may be able to do this in searchDisplayController: willShowSearchResultsTableView`

    • если есть результаты поиска для отображения или isLoading == NO
      • seachTableOverlayView.hidden == YES
    • иначе (если isLoading == YES)
      • searchTableOverlayView.frame == searchResultsTableView.frame
      • добавить seachTableOverlayView в качестве подпредставления searchTableVIew.superview
      • searchTableView.hidden = YES
  5. когда ваш фоновый фильтр завершен

    • так же, как вариант 1
    • если есть searchResults для отображения
      • searchTableCoverView.hidden = YES
      • searchResultsTableView.hidden = NO
    • еще
      • searchResultsTableView.hidden = YES
      • searchTableCoverView.hidden = NO
  6. в различных методах делегата tableView отвечают, как вы хотите показать статус, если есть текущие результаты поиска или результаты загружаются в фоновом режиме.То, что я сделал:

    • так же, как вариант 1
0 голосов
/ 22 июля 2013

Скрыть self.searchDisplayController.searchResultsTableView, пока пользователь не нажмет кнопку поиска

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView;
{
    tableView.hidden = YES;
}

После того, как пользователь нажмет кнопку поиска, и результаты поиска будут готовы, сделайте таблицу результатов поиска видимой

self.searchDisplayController.searchResultsTableView.hidden = NO;
[self.searchDisplayController reloadData]

Этот обходной путь работает для меня.

0 голосов
/ 17 декабря 2012

Когда я столкнулся с той же проблемой, я попытался наложить вид на представление результатов поиска.Это не помогло мне.Похоже, Apple изменила свое поведение, и я увидел, что в моем поле зрения светятся разделители клеток.Наконец, я нашел хороший подход.

Сначала у моего класса асинхронного поиска были свои оверлеи, прогресс и другие представления.UISearchDisplayController использовался только для запуска, завершения вызовов методов делегата и соблюдения потока поиска по умолчанию.Чтобы показать представление, я использовал любое подпредставление, на которое я могу включить виды поиска (как вызов инициализации):

newView.frame = frame;
[view addSubview:newView];

, а затем использовать подпредставление при изменении моих просмотров прогресса поиска:

if (view == currentView)
    return;

view.frame = currentView.frame;
view.alpha = [self getAlphaValueForView:view];

UIView * superView = [currentView superview];
[currentView removeFromSuperview];

currentView = view;
[superView addSubview:currentView];

Проблема с миганием представления пустой таблицы результатов поиска появляется, когда я начинаю использовать свой контроллер контента поиска в стандартной процедуре навигации (контроллер навигации).

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

Итак, в общем: НЕ используйте контроллер представления контента UISearchDisplayController в навигации.Используйте контроллер заглушки.А затем используйте его представление, чтобы поместить ваши представления в качестве подпредставлений.

Отлично сработало для меня.

0 голосов
/ 06 марта 2011

К сожалению, я верю, что именно так работает UISearchDisplayController.Вам следует отправить отчет об ошибке в Apple, если вы хотите запросить различные варианты функциональности.

Альтернативой может быть написание собственной комбинации UISearchBar и UITableView, аналогичной тому, как работает UISearchDisplayController, тогда выВы получите лучший контроль.

Надеюсь, это поможет!

0 голосов
/ 03 марта 2011

Может быть, вам нужно реализовать UISearchDisplayController, а затем эту функцию:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
...