NSFetchedResultsController reports Update when it should report Move

Hi,


I have a problem that's driving me crazy, so any help is appreciated.


The setup: we have a table view that's using an NSFetchedResultsController to display data. The fetch request is really simple: it loads all entities from a table, sorted by a date field. The CoreData stack uses the NSPersistentContainer, the fetch request loads from the default view context, new data is loaded from a server and saved in a background context created with newBackgroundContext(). The view context has automaticallyMergesChangesFromParent set to true.


The problem: if an entity gets its date field updated, in a way that the sort order is changed, the NSFetchedResultsController reports the change, but only as an update, not as a move. So the cell is correctly updated with the new data, including the date, but does not change its position as it should, indexPath and newIndexPath are identical.


Some observations: just doing tableView.reloadData() does not solve the problem, but doing a perform fetch before does. Doing the updates and save on the view context also works. But obviously, both solutions are far from ideal.


Also: the bug only seems to happen if cells far down are updated, but if cells that are visible are updated, it usually works.


So I suspect that the bug only occurs if entities not already fully loaded are updated. It's just weird that it recognizes the update, but not the change in the sort order.


I also played around with merge policies, but that did not seem to change anything.


Please help :-(

Replies

This happens to me as well. Looks like a new bug in iOS 12.

Right, so after almost giving up we finally found a solution/workaround. The problem seems to be that the loaded objects are faulted and that the date field on which the sorting is based is not loaded. So we force the date field to be loaded using FetchRequest's propertiesToFetch list.


It's kind of sad/surprising that this is necessary, but it seems to do the trick.

I believe I found the cause of this. We had set fetchBatchSize ont he fetchedResultsController's fetchRequest. When there is a batch size, updates to items above that limit which are not fetched to memory are not reported as moves even if they should move to the top. Removing it fixes the bug. Of course this a huge bug of Apple and was working in previous versions of iOS/XCode. It's really irritating that Apple always has some huge bug with this class in every iOS version which they never fix.