performFetch creating diffable data source snapshots with too much data

458 Views Asked by At

After executing an NSBatchBatchInsertRequest and calling fetchedResultsController.performFetch(), the frc’s delegate method controller(_:didChangeContentWith:) is called with a NSDiffableDataSourceSnapshot<Section, NSManagedObjectID> that unexpectedly contains all data in Core Data.

However I've only just inserted new data into Core Data. Applying a snapshot with all the data at each performFetch is causing a high memory load and jittery scrolling when I test this with thousands of cells.

Is there a way to make this delegate method only receive a snapshot with incremental updates to the data source?

Code

Here's how the NSFetchedResultsController is created:

let fetchedResultsController = NSFetchedResultsController<MyManagedObject>(
        fetchRequest: fetchRequest,
        managedObjectContext: persistentContainer.viewContext,
        sectionNameKeyPath: nil,
        cacheName: nil
    )

The NSFetchRequest:

let fetchRequest = MyManagedObject.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "value", ascending: true)]
fetchRequest.fetchBatchSize = 10

The snapshot is applied in this NSFetchedResultsControllerDelegate method below.

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
    dataSource.apply(snapshot as NSDiffableDataSourceSnapshot<Section, NSManagedObjectID>, animatingDifferences: false)
}

The most obvious solution to me was implementing this delegate method only, but that method doesn't seem to get called:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith diff: CollectionDifference<NSManagedObjectID>) {
    print(diff)
}

Data source to Core Data connection

  • When the data source is asked to make a cell for a specific NSManagedObjectID, the right MyManagedObject is found for that NSManagedObjectID using fetchedResultsController.managedObjectContext.object(with:).
  • Then the MyManagedObject is converted into an Item, which is finally used to configure the cell.
0

There are 0 best solutions below