1

问题

在执行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 转换并存储ItemMyManagedObject实例。
  • performFetch()然后被调用main
  • 调用performFetch()可确保在 中提供新的快照controller(_:didChangeContentWith:),数据源可以apply(_:animatingDifferences:completion:)更新 UI。
  • 这些项目填充 a UICollectionView,它连接到 a UICollectionViewDiffableDataSource<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 中,那么为什么我会在快照中获取所有数据?

4

0 回答 0