问题
在执行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 中,那么为什么我会在快照中获取所有数据?