1

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.

https://github.com/robbiehanson/XMPPFramework/blob/master/Extensions/CoreDataStorage/XMPPCoreDataStorage.m

EDIT: Just verified that it works when there is no predicate.

p0lAris
  • 4,750
  • 8
  • 45
  • 80
  • In your code sample it is not visible where you set 'roomJID'.Then, did you check the spelling of 'roomJIDString' in the predicate? Upper and lower case and so on? – Olaf Oct 03 '14 at 13:35

0 Answers0