DiffableDataSource с несколькими типами ячеек
Я смотрю на DiffableDataSource, доступный в iOS13 (или перенесен сюда: https://github.com/ra1028/DiffableDataSources), и не могу понять, как можно было бы поддерживать несколько типов ячеек в вашей коллекции или представлении таблицы.
Пример кода Apple 1 имеет:
var dataSource: UICollectionViewDiffableDataSource<Section, OutlineItem>! = nil
который, кажется, заставляет источник данных быть единственным типом ячейки. Если я создаю отдельный источник данных для другого типа ячеек - тогда нет никакой гарантии, что оба источника данных не имеют apply
призвал их в то же время - что привело бы к страшным NSInternalInconsistencyException
- который знаком любому, кто пытался анимировать вставку / удаление клеток вручную с performBatchUpdates
,
Я что-то упускаю из виду?
3 ответа
Я заключил свои разные данные в enum
со связанными значениями. В моем случае источник данных был типаUICollectionViewDiffableDataSource<Section, Item>
, где Item
был
enum Item: Hashable {
case firstSection(DataModel1)
case secondSection(DataModel2)
}
затем в вашем закрытии, переданном в инициализацию источника данных, вы получите Item
, и при необходимости вы можете протестировать и развернуть данные.
(Я бы добавил, что вы должны убедиться, что ваши поддерживающие связанные значения Hashable
, иначе вам нужно будет это реализовать. Это то, что алгоритм сравнения использует для идентификации каждой ячейки, разрешения перемещений и т. Д.)
Вам определенно нужно иметь один источник данных.
Ключ должен использовать более общий тип. Свифта AnyHashable
хорошо работает здесь. И вам просто нужно привести пример AnyHashable
в более конкретный класс.
lazy var dataSource = CollectionViewDiffableDataSource<Section, AnyHashable> (collectionView: collectionView) { collectionView, indexPath, item in
if let article = item as? Article, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Section.articles.cellIdentifier, for: indexPath) as? ArticleCell {
cell.article = article
return cell
}
if let image = item as? ArticleImage, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Section.trends.cellIdentifier, for: indexPath) as? ImageCell {
cell.image = image
return cell
}
fatalError()
}
И перечисление Section выглядит так:
enum Section: Int, CaseIterable {
case articles
case articleImages
var cellIdentifier: String {
switch self {
case .articles:
return "articleCell"
case .articleImages:
return "imagesCell"
}
}
}
Одним из способов достижения этого может быть использование вашегоSection
enum для идентификации раздела сindexPath.section
. Это будет примерно так:
lazy var dataSource = UICollectionViewDiffableDataSource<Section, Item> (collectionView: collectionView) { collectionView, indexPath, item in
let section = Section(rawValue: indexPath.section)
switch section {
case .firstSection:
let cell = ... Your dequeue code here for first section ...
return cell
case .secondSection:
let cell = ... Your dequeue code here for second section ...
return cell
default:
fatalError() // Here is handling the unmapped case that should not happen
}
}