IOS: example code SharedCoreData (iCloud + CoreData) | How to merge changes

I am trying to adopt WWDC 2012 sample code for iCloud and CoreData ( link to github sample code ) and need some help to understand what is going on there.

I have a table view that takes its contents from NSFetchedResultsController, as in the example. The NSFetchedResultsController is associated with the main NSManagedObjectContext of the CoreDataController shown in the example. Changes in inputs are synchronized 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 have seen many examples where NSPersistentStoreDidImportUbiquitousContentChangesNotification is used to merge changes, but never happens in this code.

But here's the weird thing: I take an object from the main context and hold it. If I get NSPersistentStoreDidImportUbiquitousContentChangesNotification, I use objectId and reload the object from NSMangedObjectContext:

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

But the object is not updated. Even if I select with a predicate using the unique property of the object. But table view with NSFetchedResultsController shows the changes. What am I missing here?

EDIT 1 (After reading Tom's answer):

I added an observer for NSPersistentStoreDidImportUbiquitousContentChangesNotification :

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

The refreshObject method uses NSManagedObjectID to retrieve the object from the main MOC, but it is still an old version.

+4
source share
2 answers

It could be an iOS bug. See this topic: http://devforums.apple.com/message/735512#735512

This is fixed for me:

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

It did not help:

 [moc refreshObject:myObject mergeChanges:YES]; 
+4
source

The lack of NSPersistentStoreDidImportUbiquitousContentChangesNotification is a pretty significant omission from the SharedCoreData sample code. You definitely need to watch this, and the fact that you are not doing this is directly related to the lack of updated values. If you should exit the application and restart it, you will probably get the new values ​​that you expect.

In the simplest case, you need to do two things when you receive this notification:

  • Call -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:notification] with notification of incoming change as an argument. This will notify your MOC of the new values. If you have unsaved changes in memory, they will be merged with the incoming changes in accordance with the MOC merge policy (see the constants listed in the documents for NSMergePolicy for NSMergePolicy ).
  • Start the deduplication process. The sample code has an example implementation of this. You will need to look at it and see if it fits your data model - that is, whether it detects duplicates correctly.
+1
source

Source: https://habr.com/ru/post/1442103/


All Articles