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):
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
didChangeContent method
Cell Registration
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 }