Basically using the mainThreadManagedObjectContext
to fetch objects —
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController == nil)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *moc = [roomStorage mainThreadManagedObjectContext];
NSEntityDescription *messageEntity = [roomStorage messageEntity:moc];
[fetchRequest setEntity:messageEntity];
[fetchRequest setFetchBatchSize:20];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(roomJIDString == %@)", roomJID];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:nil
cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
return fetchedResultsController;
}
In the background however, there is a method to insert object using a background managedObjectContext. The changes are then scheduled to save. And the following method is called when the internal managedObjectContext is saved:
- (void)managedObjectContextDidSave:(NSNotification *)notification
{
NSManagedObjectContext *sender = (NSManagedObjectContext *)[notification object];
if ((sender != mainThreadManagedObjectContext) &&
(sender.persistentStoreCoordinator == mainThreadManagedObjectContext.persistentStoreCoordinator))
{
XMPPLogVerbose(@"%@: %@ - Merging changes into mainThreadManagedObjectContext", THIS_FILE, THIS_METHOD);
dispatch_async(dispatch_get_main_queue(), ^{
// http://stackoverflow.com/questions/3923826/nsfetchedresultscontroller-with-predicate-ignores-changes-merged-from-different
for (NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
[[mainThreadManagedObjectContext objectWithID:[object objectID]] willAccessValueForKey:nil];
}
[mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
[self mainThreadManagedObjectContextDidMergeChanges];
});
}
}
The issue is that my controllerDidChangeContent
is never called. Please bear in mind that the internal/background managedObjectContext
is not updating the objects; in fact adding new ones.
If you want to see the see the specific core data code, I am using it from the XMPPFramework.
EDIT: Just verified that it works when there is no predicate.