Настройте UITableViewDiffableDataSource со снапшотом
Замените классическую таблицу на cellForRowAt на diffable data source. Даны enum Section и список значений Item — постройте data source и примените начальный снапшот, чтобы строки появились.
Ограничения:
- Используйте
UITableViewDiffableDataSourceс замыканием cell-provider. - Применяйте элементы через
NSDiffableDataSourceSnapshot, а неreloadData.
enum Section { case main }
var dataSource: UITableViewDiffableDataSource<Section, Item>!
func configureDataSource(_ tableView: UITableView, items: [Item]) {
// ваш код здесь
}
Допишите реализацию.
Постройте data source с замыканием cell-provider под каждый Item. Создайте NSDiffableDataSourceSnapshot, вызовите appendSections([.main]) и appendItems(items), затем dataSource.apply(snapshot). В отличие от reloadData, он анимирует лишь изменившиеся строки.
- ✗Зовут
reloadDataвместо применения снапшота - ✗Забывают
appendSectionsпередappendItems - ✗Думают, что diffable data source только для collection view
- →Как
apply(_:animatingDifferences:)выбирает анимации строк? - →Почему
Itemдолжен бытьHashable, чтобы сравнение работало?
Data source описывает ячейки через cell-provider, а данные приезжают снапшотом:
func configureDataSource(_ tableView: UITableView, items: [Item]) {
dataSource = UITableViewDiffableDataSource<Section, Item>(tableView: tableView) {
table, indexPath, item in
let cell = table.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = item.title
return cell
}
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
dataSource.apply(snapshot, animatingDifferences: true)
}
Каждый последующий apply нового снапшота сравнивает старое и новое состояние по Hashable-идентичности Item и анимирует только вставки, удаления и перемещения — без ручного insertRows/deleteRows и без рассинхронов, которыми грешит reloadData при мутации массива.