Search code examples
ioscore-dataicloud

iOS: SharedCoreData Example Code (iCloud + CoreData) | How are changes merged


I'm trying to adopt the WWDC 2012 example code for iCloud and CoreData (link to github sample code) and need some help understanding what's going on there.

I have a table view that takes its contents from a NSFetchedResultsController just like in the example. The NSFetchedResultsController is connected with the main NSManagedObjectContext from the CoreDataController provided by the example. Changes to entrys are synced from one device to another and it works like a charm. But there is no place where changes from iCloud are actually merged into the main context. I've seen a lot of examples where the NSPersistentStoreDidImportUbiquitousContentChangesNotification is used to merge the changes, but in this code that never happens.

But here is the strange thing: I take an object from the main context and hold it. If I receive the NSPersistentStoreDidImportUbiquitousContentChangesNotification I use the objectId and reload the object from the NSMangedObjectContext:

NSManagedObjectID* objectId = [myObject objectID];
NSManagedObject* theNewObject = [[_coreDataController mainThreadContext] objectWithID:objectId];
myObject = theNewObject;

But the object is not up to date. Even if I do a fetch with a predicate using a unique property of the object. But the table view with the NSFetchedResultsController shows the changes. What am I missing here?

EDIT 1 (After reading Tom's answer):

I added an observer for the NSPersistentStoreDidImportUbiquitousContentChangesNotification:

- (void)iCloudupdate:(NSNotification*)note {
    NSManagedObjectContext* moc = [[CoreDataController sharedController] mainThreadContext];
    [moc performBlock:^{
        [moc mergeChangesFromContextDidSaveNotification:note];
        [self refreshObject];
    }];
}

The method refreshObject uses the NSManagedObjectID to fetch the object from the main MOC, but it's still an old version.


Solution

  • This may be an iOS bug. See this thread: http://devforums.apple.com/message/735512#735512

    This fixed it for me:

    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    moc.stalenessInterval = 0;
    

    This didn't help:

    [moc refreshObject:myObject mergeChanges:YES];