问题
在执行NSBatchBatchInsertRequest和调用之后fetchedResultsController.performFetch(),frc 的委托方法controller(_:didChangeContentWith:)被调用,NSDiffableDataSourceSnapshot<Section, NSManagedObjectID>其中意外地包含了 Core Data 中的所有数据(即使我刚刚插入了新数据)。
代码
以下是它的NSFetchedResultsController创建方式:
let fetchedResultsController = NSFetchedResultsController<MyManagedObject>(
fetchRequest: fetchRequest,
managedObjectContext: persistentContainer.viewContext,
sectionNameKeyPath: nil,
cacheName: nil
)
NSFetchRequest:_
let fetchRequest = MyManagedObject.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "value", ascending: true)]
fetchRequest.fetchBatchSize = 10
快照应用在下面的这个NSFetchedResultsControllerDelegate方法中。
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
dataSource.apply(snapshot as NSDiffableDataSourceSnapshot<Section, NSManagedObjectID>, animatingDifferences: false)
}
细节
Item示例应用程序每 5 秒接收 10,000 个实例,并NSBatchInsertRequest在新的后台上下文中运行一个performAndWait以将 s 转换并存储Item为MyManagedObject实例。performFetch()然后被调用main。- 调用
performFetch()可确保在 中提供新的快照controller(_:didChangeContentWith:),数据源可以apply(_:animatingDifferences:completion:)更新 UI。 - 这些项目填充 a
UICollectionView,它连接到 aUICollectionViewDiffableDataSource<Section, NSManagedObjectID>。- 当数据源被要求为一个特定的单元格创建一个单元格时
NSManagedObjectID,正确MyManagedObject的为那个NSManagedObjectID使用fetchedResultsController.managedObjectContext.object(with:)。 - 然后将
MyManagedObject转换为Item,最终用于配置单元格。
- 当数据源被要求为一个特定的单元格创建一个单元格时
尝试解决方案
对我来说最明显的解决方案是仅实现此委托方法,但该方法似乎没有被调用:
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith diff: CollectionDifference<NSManagedObjectID>) {
print(diff)
}
我不希望用户界面在获取数据时出现卡顿和挂起。我认为发生这种情况的原因是因为我的快照很大。我猜为什么它们很大是因为我的获取请求获取了所有数据(但我只想将新数据添加到快照中)。为了解决这个问题,我尝试设置fetchLimit一个像 2 这样的小数字,但这只会导致只获取 2 个项目。我想我可以通过更新来解决这个问题fetchOffset,但是当我滚动时这种方法可能会变得混乱。调整fetchBatchSize并没有什么不同。内存也没有泄漏。FWIW,我在后台队列中应用快照,但这似乎也没有改善 UI 卡顿。
我想在获取项目时将它们存储到 Core Data,然后仅在滚动到屏幕外单元格时从持久存储中获取。这似乎正在发生,因为当应用快照时,我可以看到数据源仅请求可见范围附近的索引路径的单元格(即使集合视图的垂直滚动条随着时间的推移而缩小)。但是快照的大小(= 到目前为止收到的项目总数)一直在增加。
我可以获得当前快照,并且只附加新快照中缺少的项目,但这仍然需要我通过无限大小的快照。我怎样才能避免这样做并加载大量数据而不会出现 UI 卡顿?我只是将新数据插入到 Core Data 中,那么为什么我会在快照中获取所有数据?