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"
            }
        }
    }

Одним из способов достижения этого может быть использование вашегоSectionenum для идентификации раздела с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
        }
    }
Другие вопросы по тегам