UICollectionViewCompositionalLayout не может использовать те же разделы, что и UICollectionViewDiffableDataSource?

Я создаю контроллер представления с представлением коллекции, используя (своего рода) новый источник данных для различий и составной макет представления коллекции. Я сделал свои собственные перечисления Section и Row, могу реагировать на изменения в моей модели (массив фотографий), что вызывает applySnapshot и все работает.

Но.. по моему createLayoutфункция У меня есть только индекс раздела для работы?? Мне это кажется очень странным, почему эти две технологии не работают лучше вместе? Один работает с SectionIdentifierType и ItemIdentifierType(отлично!), а другой по-прежнему основан на индексах? Тьфу.

Я хочу сделать что-то вроде этого: все ячейки внутри Section.headerРаздел должен быть на всю ширину экрана с автоматической высотой. Каждая ячейка в Section.photosраздел получит фиксированный размер. Также могут быть другие разделы с разными размерами ячеек, а некоторые разделы могут быть необязательными. Таким образом, с системой на основе индексов действительно сложно работать, нельзя жестко запрограммировать, что раздел 0 - это заголовок, а раздел 1 - это фотографии: порядок может меняться, все может быть необязательным и т. Д.

Что лучше с этим справиться? Я, конечно, могу хранить массив [Section] на контроллере представления используйте индекс раздела, чтобы получить Sectionв таком случае, но нет ли встроенного способа получить идентификатор раздела для индекса? Это кажется вполне логичным, поскольку эти две технологии были выпущены одновременно.

class PhotosViewController: UIViewController {
  enum Section: Equatable, Hashable {
    case header
    case photos
  }

  enum Row: Equatable, Hashable {
    case header
    case photo(Photo)
  }

  private lazy var dataSource = makeDataSource()
  var photos: AnyPublisher<[Photo], Never>!

  override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.collectionViewLayout = createLayout()

    photos
      .sink(receiveValue: applySnapshot)
      .store(in: &subscriptions)
  }

  private func makeDataSource() -> UICollectionViewDiffableDataSource<Section, Row> {
    return UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, item) -> UICollectionViewCell? in
      switch item {
        case .header:
          let cell = collectionView.dequeueReusableCell(for: indexPath, cellType: ProfileHeaderCollectionViewCell.self)
          return cell

        case .photo(let photo):
          let cell = collectionView.dequeueReusableCell(for: indexPath, cellType: PhotoCollectionViewCell.self)
          cell.configure(photo: photo)
          return cell
      }
    }
  }

  private func applySnapshot(photos: [Photo]) {
    var snapshot = NSDiffableDataSourceSnapshot<Section, Row>()

    let headerSection = Section.header
    snapshot.appendSections([headerSection])
    snapshot.appendItems([.header], toSection: headerSection)

    let items = photos.map { Row.photo($0) }
    let photosSection = Section.photos
    snapshot.appendSections([photosSection])
    snapshot.appendItems(items, toSection: photosSection)

    dataSource.apply(snapshot, animatingDifferences: false)
  }

  private func createLayout() -> UICollectionViewLayout {
    let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, _ in
      // I have to work with a sectionIndex instead of a Section case?
    }

    return layout
  }
}

1 ответ

Вместо того, чтобы отслеживать идентификаторы разделов в отдельном массиве, к счастью, вы можете просто использовать dataSource.snapshot().sectionIdentifiers[sectionIndex].

Другие вопросы по тегам