I'm using NSFetchedResultsController with sortDescriptors on the request to populate a table with a lot of results in it. I notice that when a change occurs that moves a row from near the bottom of the table to the top, didChangeObject:atIndexPath:forChangeType:newIndexPath: is not called at all.
Strangely, I can work around this by iterating through all the fetched objects and accessing any attribute on them right after calling performFetch.
Any tips on what the problem might be, or is this just an obscure Apple bug?
Here is my code:
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"MyObject" inManagedObjectContext:context];
request.sortDescriptors = @[NSSortDescriptor sortDescriptorWithKey:@"order" ascending:NO]];
request.fetchBatchSize = 20;
NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc]
                                       initWithFetchRequest:request
                                       managedObjectContext:context
                                         sectionNameKeyPath:nil
                                                  cacheName:nil];
fetched.delegate = self;
NSError *error = nil;
if (![fetched performFetch:&error]) {
    NSLog(@"Unresolved error fetching objects: %@", error);
}
// Should not be necessary, but objects near the bottom won't move to the top without it.
for (MyObject *o in fetched.fetchedObjects) {
    o.someAttribute;
}
Updated September 12, 2014:
I'm saving all data in a background managed object context, and it seems to be related to the issues I'm seeing. Here is my code for merging changes from to the main object context:
+(void)initSaveListener {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:)
                                                 name:NSManagedObjectContextDidSaveNotification
                                               object:[self privateContext]];
}
+(void)mergeChanges:(NSNotification*)notification {
    NSManagedObjectContext *context = [self mainContext];
    [context performBlock:^{
        [context mergeChangesFromContextDidSaveNotification:notification];
        NSError *error = nil;
        if (![context save:&error]) {
            NSLog(@"error merging changes %@, %@", error, [error userInfo]);
        }
    }];
}