I am facing a strange problem when the NSFRC array fetchedObjects does not return all the objects that it needs. To give you some context, my application has several list view controllers, each of which has an NSFRC. I am updating the list view in the delegate method method of DidChangeContent. The problem I encountered is this: after saving the object in the background MOC and saving it, the DidChangeContent controller is called, but the object that I just saved in the background stream does not appear in NSFRC. Here is a piece of code that I use to test this:
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { NSManagedObjectContext *context = controller.managedObjectContext; NSError *error = nil; NSArray *array = [context executeFetchRequest:controller.fetchRequest error:&error]; if (nil != array) { NSUInteger count = MIN(controller.fetchedObjects.count, array.count); for (NSUInteger index=0; index<count; index++) { NSManagedObject *a = array[index]; NSManagedObject *b = controller.fetchedObjects[index];
I expect the NSFRC array fetchedObjects to be identical to the array returned by manual execFetchRequest (I use NSFRC fetchRequest to manually fetch data). However, it is not. Manual executeFetchRequest returns more than NSFRC fetchedObjects. Does anyone know what is going on? I disabled caching in the NSFRC, but the same behavior is reported.
Thanks!
=== Update ====
Some update on this issue. I think there is an error in Core Data, because I was able to see some inconsistent results from NSFRC and, in addition, I was able to fix this problem by circumventing the solution regarding "touching" the object in question. Here is a script that explains what happens:
Imagine the following Core Data model, where: - There are Cat objects and Master objects. βA Cat can have one or more Masters.β - A master can have one or more cats. - The first NSFRC (let it be called NSFRC_A) was created to retrieve all cats with a master named "Master_A". Predicate: {ANY master.name == "Master_A"}. - The second NSFRC (let it be called NSFRC_B) was created to retrieve all cats with a master named "Master_B". Predicate: {ANY master.name == "Master_B"}. - There is a context for the main managed entity that is used only in the user interface thread. - For each background thread, a background managed object is created using the same persistent storage as the main context of the managed object.
A cat named "Cat_A" is created in the background and assigned to the master "Master_A". After saving the background context, the main context is updated accordingly. At this point, NSFRC_A notifies its delegate that a change has occurred and correctly reports βCat_Aβ.
Later, in the background thread, the same cat "Cat_A" is assigned the master "Master_B". After saving the background context, the main context is updated accordingly. At this point, NSFRC_A notifies its delegate of this change and correctly reports "Cat_A". NSFRC_B also notifies its delegate of this change, but does not report "Cat_A" (it is not in its fetchedObjects). However, if I manually fetch using the same fetchRequest as NSFRC_B, I can see the returned "Cat_A". It is strange that the returned instance of "Cat_A" is flagged as an error that explains why NSFRC_B does not return "Cat_A" because it does not see it in memory.
This is a mistake because I can fix this behavior by simply registering the βCat_Aβ connection with the wizard when changes from the background thread are merged into the main context: registration mainly concerns the object and forces it to implement memory.