Я использую экран поиска в моем приложении, используя 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.