DiffableDataSource:快照不会重新加载标题和页脚 [英] DiffableDataSource: Snapshot Doesn't reload Headers & footers

查看:28
本文介绍了DiffableDataSource:快照不会重新加载标题和页脚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using UICollectionViewDiffableDataSource for UICollectionView to display content in multiple sections.

我正在使用 Collection View Compositional Layout 和 Diffable Datasources link在 WWDC'19 上引入以呈现 UICollectionView

I am using Collection View Compositional Layout and Diffable Datasources link which was introduced at WWDC'19 to render the Multiple Section Layout of UICollectionView

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

I have a simple setup, The Header for each section shows number of items in that section, and Footer shows the summary of all items of the section.

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

section 1 Header --> January 2020 - 5 Trips
section 1 item 1 --> Trip 1
section 1 item 2 --> Trip 2
section 1 item 3 --> Trip 3
section 1 item 4 --> Trip 4
section 1 item 5 --> Trip 5

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

now If a trip is deleted, the DiffableDataSource updates the change by animation but it doesn't reload the Headers of the sections. Which looks inconsistent. E.g. If the Trip 4 was deleted then Header still shows that there are 5 trips in the section. How can I have headers also reload with the DiffableDataSource?

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

for a temporary fix, I just call collectionView.reloadData() after a delay which shows the Diffing animation and then I hard reload the data which forces the header to be reloaded as well.

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

推荐答案

要触发 headers 的自动重新加载,您的 Section 对象应该Hashable 并且应该存储所有必要的属性来为该部分创建一个唯一的散列.

To trigger an automatic reload of headers your Section object should be Hashable and should have all the necessary properties stored to create a unique hash for the Section.

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

That's why all Section objects and Item objects should be Hashable and they should return a unique hash to allow DiffableDataSource to manage their reload only if their values were changed.

例如:

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

然后:

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

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

Any change of the title or items count for the section during the next update of the snapshot will trigger section header to reload and it will work like magic!

这篇关于DiffableDataSource:快照不会重新加载标题和页脚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆