I have an NSFetchedResultsController which fetches objects with a predicate:
isTrash == NO
Most of the time this works as expected, but when an object gets untrashed the fetched results controller does not fetch the untrashed object.
What's going wrong?
The reason why this is happening is due to how
mergeChangesFromContextDidSaveNotification:
handles updated objects.NSManagedObjectContext
keeps a record of objects which are in use in the context, these are referred to as registered objects (NSManagedObjectContext
has methods for accessing and conditionally fetching registered objects).mergeChangesFromContextDidSaveNotification:
only processes updates for objects which are registered in the context. This has a knock on effect forNSFetchedResultsControllers
that explains the cause of the problem.Here's how it plays out:
A FRC is setup with a predicate that doesn't match all objects (thus preventing the objects which do not match the predicate from being registered in the FRCs context).
A second context makes a change to an object which means that it now matches the FRCs predicate. The second context is saved.
The FRCs context processes the
NSManagedObjectContextDidSaveNotification
but only updates its registered objects, therefore it does not update the object which now matches the FRC predicate.The FRC does not perform another fetch when there's a save, therefore isn't aware that the updated object should be included.
The fix
The solution is to fetch all updated objects when merging the notification. Here's an example merge method:
Try setting
shouldRefreshRefetchedObjects
toYES
on theNSFetchRequest
for your fetched results controller.