Как я могу перезагрузить элементы без удаления и вставки с UITableViewDiffableDataSource? - PullRequest
1 голос
/ 10 марта 2020

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

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

Я объявляю источник данных следующим образом:

@property (retain) UITableViewDiffableDataSource<NSString *, SearchHit *> *dataSource;

SearchHit представляет один результат поиска; у него есть свойства для отображаемого заголовка и массив диапазонов для выделения в заголовке. И он переопределяет hash и isEqual:, так что каждая строка результата уникально идентифицируется.

Мой код выглядит примерно так:

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
  NSArray<SearchHit *> *hits = [self fetchHits:searchText];
  NSDiffableDataSourceSnapshot<NSString *, SearchHit *> *snap = [[[NSDiffableDataSourceSnapshot alloc] init] autorelease];
  [snap appendSectionsWithIdentifiers:@[@""]];
  [snap appendItemsWithIdentifiers:hits];
  [snap reloadItemsWithIdentifiers:hits];
  [self.dataSource applySnapshot:snap animatingDifferences:YES];
}

Сначала у меня не было reloadItemsWithIdentifiers позвоните туда, и тогда ни одна ячейка не изменится вообще, как только она окажется в списке результатов. Помогло добавление вызова reload, но теперь большинство ячеек постоянно отстают на одно обновление. Это пахнет ошибкой logi c где-то в моем коде, но я убедился, что попадания, переданные в моментальный снимок, являются правильными, а попадания, переданные обратному вызову создания ячейки источника данных, не являются.

Эта статья Донни Уолса и этой связанной ветки Twitter с участием Стива Брина предполагает, что способ исправить это состоит в том, чтобы тип идентификатора элемента представлял только свойства, необходимые для отображения ячейки. Поэтому я обновил SearchHit ha sh и сравнение равенства, чтобы включить выделенные части заголовка, чего раньше не было. Затем я получил удаление и вставку анимации для всех ячеек в каждом обновлении, что мне не нужно.

Это похоже на то, что reloadItemsWithIdentifiers должен делать ... верно?

Пример проекта здесь на GitHub.

1 Ответ

1 голос
/ 10 марта 2020

API-интерфейс источника данных, который можно использовать, может быть неправильным инструментом для анимации самих ячеек. Он ориентирован на анимацию появления, исчезновения и упорядочения ячеек. Если в вашем источнике данных есть изменение, выраженное с помощью соответствия Hashable, API увидит его как изменение и удалит / вставит et c.

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

...