NSFetchedResultsController + UICollectionViewDiffableDataSource + CoreData - 如何区分整个对象?

Posted

技术标签:

【中文标题】NSFetchedResultsController + UICollectionViewDiffableDataSource + CoreData - 如何区分整个对象?【英文标题】:NSFetchedResultsController + UICollectionViewDiffableDataSource + CoreData - How to diff on the entire object? 【发布时间】:2019-10-21 12:07:21 【问题描述】:

我正在尝试使用 ios 13 中内置的一些新差异类以及 Core Data。我遇到的问题是controllerdidChangeContentWith 没有按预期工作。它传递给我一个快照引用,它是对一个

NSDiffableDataSourceSnapshot<Section, NSManagedObjectID>

意思是我得到了已更改的部分/对象 ID 的列表。

这部分效果很好。但是当您在集合视图中找到差异时,问题就来了。在 WWDC 视频中他们高兴地打电话

dataSource.apply(snapshot, animatingDifferences: true)

一切都很神奇,但在实际 API 中并非如此。

在我最初的尝试中,我尝试了这个:

resolvedSnapshot.appendItems(snapshot.itemIdentifiersInSection(withIdentifier: section).map 
     controller.managedObjectContext.object(with: $0 as! NSManagedObjectID) as! Activity
, toSection: .all)

这适用于填充单元格,但如果单元格上的数据发生更改(即单元格标题),则永远不会重新加载特定单元格。我查看了快照,看来问题只是我引用了这些活动对象,因此它们都同时更新(意味着旧快照中的活动等同于新快照中的活动,所以哈希值相等。)

我当前的解决方案是使用一个包含我的所有 Activity 类变量的结构,但这会将它与 CoreData 断开连接。所以我的数据源变成了:

var dataSource: UICollectionViewDiffableDataSource<Section, ActivityStruct>

这样快照实际上得到了两个不同的值,因为它有两个不同的对象要比较。这行得通,但似乎远非优雅,这就是我们的本意吗?还是它现在只是处于破碎状态? WWDC 视频似乎暗示它不应该需要所有这些额外的样板文件。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,我想我知道什么是有效的:

有两个类:UICollectionViewDiffableDataSourceUICollectionViewDiffableDataSourceReference

据我所知,当您使用第一个时,您将所有权作为“真相的来源”,因此您创建了一个充当数据源的对象。当您使用第二个(数据源引用)时,您将“真相来源”推迟到另一个数据源(在本例中为 CoreData)。

您将实例化 ...DataSourceReference...DataSource 基本相同的方式:

dataSourceReference = UICollectionViewDiffableDataSourceReference(collectionView: collectionView, cellProvider:  (collectionView, indexPath, object) -> UICollectionViewCell? in
    let identifier = <#cell identifier#>
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath)

    <#cell configuration#>
            
    return cell
)

然后当你实现NSFetchedResultsControllerDelegate时,你可以使用以下方法:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference)

    dataSourceReference.applySnapshot(snapshot, animatingDifferences: true)


我也观看了 WWDC 视频,但没有看到相关内容。不得不犯一些错误才能到达这里。我希望它对你有用!

【讨论】:

以上是关于NSFetchedResultsController + UICollectionViewDiffableDataSource + CoreData - 如何区分整个对象?的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?