NSFetchedResultsControllerDelegate didChangeContentWith called with temporary CoreData Ids on save

Currently pretty confused about a DiffableDatasource, FetchedResultsController, & CollectionView behavior. As a result of calling the method below, the NSFetchedResultsController delegate didChangeContentWith method is called with a snapshot that contains temporary NSManagedObjectIds. As a result, when cell registration vend block is called, it is given the temporary id as the item id which no longer is valid as the object has been saved. So trying to retrieve the object to create the configuration for the cell fails.

Here is snippet of the log produced by the code below (adding 2 new items):

Code Block
pre-save
didChangeContentWith
Printing description of snapshot:
<NSDiffableDataSourceSnapshot 0x2838cb660: numberOfSections:1 numberOfItems:5; generation=4EAC45D6-A145-4F4C-8220-F6EE212C3F88; sectionCounts=[_UIDataSourceSnapshotter - 0x283ab3fe0:(0:5)]
[d69e6c783a242772974cfc99189691b88e9d37c3: {0x94cd5e7b72fa7e83 <x-coredata://988F6C04-1529-454C-BBCB-2DE610F7AFC0/PlaylistItem/p2> 0x94cd5e7b729a7e83 <x-coredata://988F6C04-1529-454C-BBCB-2DE610F7AFC0/PlaylistItem/p1> 0x94cd5e7b72da7e83 <x-coredata://988F6C04-1529-454C-BBCB-2DE610F7AFC0/PlaylistItem/p3> 0x283a5a8e0 <x-coredata:///PlaylistItem/t710323F2-7D5C-40C4-A055-F75F8E0D0C852> 0x283aaf8a0 <x-coredata:///PlaylistItem/t710323F2-7D5C-40C4-A055-F75F8E0D0C853>}]>
post save
getting cell for [0, 0] with objid: 0x94cd5e7b72fa7e83 <x-coredata://988F6C04-1529-454C-BBCB-2DE610F7AFC0/PlaylistItem/p2>
getting cell for [0, 1] with objid: 0x94cd5e7b729a7e83 <x-coredata://988F6C04-1529-454C-BBCB-2DE610F7AFC0/PlaylistItem/p1>
getting cell for [0, 2] with objid: 0x94cd5e7b72da7e83 <x-coredata://988F6C04-1529-454C-BBCB-2DE610F7AFC0/PlaylistItem/p3>
getting cell for [0, 3] with objid: 0x283a5a8e0 <x-coredata:///PlaylistItem/t710323F2-7D5C-40C4-A055-F75F8E0D0C852>
Fatal error: Managed object should be available: file Stoppage/PlaylistDetail2FRCViewModel.swift, line 118
2021-05-05 11:43:10.611464-0500 Stoppage[5055:2243531] Fatal error: Managed object should be available: file Stoppage/PlaylistDetail2FRCViewModel.swift, line 118


The datasource is passing the temporary id (which is no longer available post save) to the cell creation. I can fully accept that I might be being dim and not seeing my mistake, but I just can't see it. It seems to me that the snapshot generated from the save should have the real objectIds rather than the temps. The end result is that the fatalError() in the cell registration is called as it can't find the object with the temp id.

Insert items method
Code Block
    func addItemsToPlaylist(_ newItemCollection:MPMediaItemCollection)
    {
        guard let playlist = self.playlist else {fatalError()}  
    AppDelegate.appDelegate().persistentContainer.viewContext.performAndWait {
            let pl = AppDelegate.appDelegate().persistentContainer.viewContext.object(with: playlist.objectID) as! Playlist
            pl.addMediaItems(newItemCollection)
            if AppDelegate.appDelegate().persistentContainer.viewContext.hasChanges {
                do {
                    print("pre-save")
                    try AppDelegate.appDelegate().persistentContainer.viewContext.save()
                    print("post save")
                } catch {
                    let nserror = error as NSError
                    fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                }
            }
        }
    }


didChangeContent method
Code Block
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
         print("didChangeContentWith")
         guard let datasource = diffableDataSource else {
            assertionFailure("The data source has not implemented snapshot support while it should")
            return
        }
            datasource.apply(snapshot as NSDiffableDataSourceSnapshot<Int, NSManagedObjectID>, animatingDifferences: false)
    }


Cell Registration
Code Block
        let itemCellRegistration = UICollectionView.CellRegistration<PlaylistDetail2Cell, NSManagedObjectID> { (cell, indexPath, itemId) in
            guard let object = try? AppDelegate.appDelegate().persistentContainer.viewContext.existingObject(with: itemId) else {
                fatalError("Managed object should be available")
            }
            cell.playlistItem = object as! PlaylistItem
            cell.playlistItemId = object.objectID
        }

NSFetchedResultsControllerDelegate didChangeContentWith called with temporary CoreData Ids on save
 
 
Q