【问题标题】:DiffableDataSource: Snapshot Doesn't reload Headers & footersDiffableDataSource:快照不重新加载页眉和页脚
【发布时间】:2020-05-15 17:40:38
【问题描述】:

我将UICollectionViewDiffableDataSource 用于UICollectionView 以在多个部分中显示内容。

我正在使用 WWDC'19 中引入的 Collection View Compositional Layout 和 Diffable Datasources link 来呈现 UICollectionView 的多部分布局

我有一个简单的设置,每个部分的页眉显示该部分中的项目数,页脚显示该部分所有项目的摘要。

第 1 节标题 --> 2020 年 1 月 - 5 次旅行
第 1 部分第 1 项 --> 行程 1
第 1 部分第 2 项 --> 行程 2
第 1 部分第 3 项 --> 行程 3
第 1 部分第 4 项 --> 行程 4
第 1 节第 5 项 --> 行程 5

现在如果删除行程,DiffableDataSource 会通过动画更新更改,但不会重新加载部分的标题。这看起来不一致。例如。如果行程 4 已删除,则标题仍显示该部分中有 5 个行程。如何让标头也使用 DiffableDataSource 重新加载?

为了临时修复,我只是打电话给 collectionView.reloadData() 在显示 Diffing 动画的延迟之后,然后我硬重新加载数据,这也会强制重新加载标题。

private func configureTripDataSource(){
    tripDataSource = UICollectionViewDiffableDataSource<MonthSection, Trip>(collectionView: tripsCollectionView, cellProvider: { (collectionView, indexPath, trip) -> UICollectionViewCell? in

        // Get a cell of the desired kind.
        guard let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: TripInfoCell.reuseIdentifier,
            for: indexPath) as? TripInfoCell else { fatalError("Cannot create new TripInfoCell") }

        // Populate the cell with our item description.
        cell.trip = trip

        // Return the cell.
        return cell

    })

    tripDataSource.supplementaryViewProvider = {
       [weak self] (collectionView: UICollectionView, kind: String, indexPath: IndexPath) -> UICollectionReusableView? in

        guard let self = self else {return nil}

        if kind == TripsController.tripsMonthSectionHeaderElementKind{

            // Get a supplementary view of the desired kind.
            guard let header = collectionView.dequeueReusableSupplementaryView(
                ofKind: kind,
                withReuseIdentifier: TripSectionHeaderCell.reuseIdentifier,
                for: indexPath) as? TripSectionHeaderCell else { fatalError("Cannot create new header") }

            // setup header

            let currentSnapShot = self.tripDataSource.snapshot()
            let tripMonthSection = currentSnapShot.sectionIdentifiers[indexPath.section]

            header.titleLabel.text = tripMonthSection.title
            header.subtitleLabel.text = "\(tripMonthSection.trips.count) Trips"

            return header

        } else {
            return UICollectionReusableView()
        }

    }

    var snapshot = NSDiffableDataSourceSnapshot<MonthSection, Trip>()

    let allSections = self.tripsStore.monthSections
    snapshot.appendSections(allSections)
    for section in allSections{
        snapshot.appendItems(section.trips, toSection: section)
    }

    self.tripDataSource.apply(snapshot, animatingDifferences: true)
}

【问题讨论】:

  • 请添加页眉页脚相关代码
  • @vadian,好的,我已经添加了代码。
  • 抱歉,我忽略了您使用的是我不熟悉的supplementaryViewProvider
  • 我也有同样的问题。我试过取消标题并重新设置它,但没有运气。它仅在滚动离开屏幕并返回时才会更新。

标签: ios swift uicollectionview uicollectionviewlayout diffabledatasource


【解决方案1】:

除了改变section的标识符,就是HASH值,有时候不需要,你也可以设置

reloadSections的快照NSDiffableDataSourceSnapshot

https://developer.apple.com/documentation/uikit/nsdiffabledatasourcesnapshot/3375784-reloadsections

这将触发部分更新页脚和页眉

func buildSnapshotAndApply(animated: Bool = true) {
    
    var newSnapshot = buildSnapshot()
    newSnapshot.reloadSections(snapshot().sectionIdentifiers)
    
    apply(newSnapshot, animatingDifferences: animated)
}

【讨论】:

    【解决方案2】:

    要触发 headers 的自动重新加载,您的 Section 对象应该是 Hashable 并且应该存储所有必要的属性以创建唯一的哈希为节。

    这就是为什么所有 Section 对象和 Item 对象都应该是 Hashable 并且它们应该返回一个唯一的哈希以允许 DiffableDataSource em> 仅在其值更改时管理其重新加载。

    例如:

    struct MonthSection: Hashable {
       var title: String
       var itemsCount: Int
    }
    

    然后:

    var section = MonthSection(title: "Title", itemsCount: 5)
    .....
    snapshot.appendSections([section])
    snapshot.appendItems(items, toSection: section)
    

    在快照的下一次更新期间,该部分的标题或项目计数的任何更改都将触发部分标题重新加载,它会像魔术一样工作!

    【讨论】:

    • 谢谢!我有部分可清洗的物体。但是我使用继承这个 Section 类的子类并在那里使用变量。现在我将变量移动到主类,一切都像魅力一样工作!
    猜你喜欢
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2012-01-25
    相关资源
    最近更新 更多