首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DiffableDataSource:快照不会重新加载标头和页脚

DiffableDataSource:快照不会重新加载标头和页脚
EN

Stack Overflow用户
提问于 2020-01-30 06:40:59
回答 2查看 4.1K关注 0票数 11

我使用UICollectionViewDiffableDataSource for UICollectionView在多个部分中显示内容。

我正在使用集合视图组成布局和可扩展数据源链接,这是在WWDC'19引入的,用于呈现UICollectionView的多段布局。

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

第1节报头->2020年1月-5次行程 第1节项目1-> Trip 1 第1节项目2-> Trip 2 第1节项目3-> Trip 3 第1节项目4-> Trip 4 第1节项目5-> Trip 5

现在,如果删除一个trip,DiffableDataSource将通过动画更新更改,但它不会重新加载各节的标题。看上去不一致。例如,如果Trip 4被删除,那么Header仍然显示该部分中有5次行程。如何使用DiffableDataSource重新加载标头?

对于临时修复,我只需在显示Diffing动画的延迟之后调用collectionView.reloadData(),然后很难重新加载强制重新加载标头的数据。

代码语言:javascript
复制
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)
}
EN

回答 2

Stack Overflow用户

发布于 2020-03-11 11:35:17

要触发headers的自动重新加载,,您的对象应该是可选的,并且应该存储所有必要的属性,以便为该节创建唯一的散列。

这就是为什么所有节、对象和Item对象都应该是Hashable的原因,它们应该返回一个惟一的散列,以允许DiffableDataSource仅在其值被更改时才能管理它们的重新加载。

例如:

代码语言:javascript
复制
struct MonthSection: Hashable {
   var title: String
   var itemsCount: Int
}

然后:

代码语言:javascript
复制
var section = MonthSection(title: "Title", itemsCount: 5)
.....
snapshot.appendSections([section])
snapshot.appendItems(items, toSection: section)

在快照的下一次更新期间,标题或项的任何更改都将触发节标题的重新加载,并且它将像魔术一样工作!

票数 15
EN

Stack Overflow用户

发布于 2020-12-09 16:00:13

除了更改节标识符之外,它的散列值(有时是不需要的)还可以设置

快照reloadSections NSDiffableDataSourceSnapshot

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

这将触发使用页脚和标头更新的部分。

代码语言:javascript
复制
func buildSnapshotAndApply(animated: Bool = true) {
    
    var newSnapshot = buildSnapshot()
    newSnapshot.reloadSections(snapshot().sectionIdentifiers)
    
    apply(newSnapshot, animatingDifferences: animated)
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59980398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档