I am presenting table view contents using NSFetchedResultsController
which has a predicate:
[NSPredicate predicateWithFormat:@"visible == %@", [NSNumber numberWithBool:YES]]
On background thread using separate NSManagedObjectContext
I update few of the entities and change theirs visible
value from NO
to YES
. Save, merge changes in main thread's NSManagedObjectContext
. But NSFetchedResultsController
's fetchedObjects
doesn't change. Also controller doesn't call -controller:didChangeObject:...
on delegate. If entities are updated on main thread in identical manner (my test app calls the same method), everything works as expected.
Also Notification's NSUpdatedObjectsKey
contains those objects.
Currently the only solutions I've found is to call for each of NSUpdatedObjectsKey
entities:
NSManagedObjectContext *context = ... // main thread context
[context existingObjectWithID:[object objectID] error:nil]
This issue is only with updated objects which previously didn't match the predicate.
Am I missing something obvious?
Turns out main NSManagedObjectContext
didn' t event fire NSManagedObjectContextObjectsDidChangeNotification
for updated objects because it is not done for faulted objects.
Generic fix (or keep a track of object IDs that needs this treatment):
NSManagedObjectContext *context = [self managedObjectContext];
for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
[[context objectWithID:[object objectID]] willAccessValueForKey:nil];
}
[context mergeChangesFromContextDidSaveNotification:notification];
From NSManagedObject Class Reference:
You can invoke this method with the key value of nil to ensure that a fault has been fired, as illustrated by the following example.
You have to call processPendingChanges on your Background-NSManagedObjectContext after you merged the changes from an other NSManagedObjectContext.
See CoreData Programming Guide:
Note that the change notification is sent in NSManagedObjectContext’s processPendingChanges method. The main thread is tied into the event cycle for the application so that processPendingChanges is invoked automatically after every user event on contexts owned by the main thread. This is not the case for background threads—when the method is invoked depends on both the platform and the release version, so you should not rely on particular timing. If the secondary context is not on the main thread, you should call processPendingChanges yourself at appropriate junctures.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With