currently i try to establish iCloud with CoreData. My app is 'only' iOS 7 based, so it is quite easy to enable iCloud. The basics are working very well (Saving to iCloud). I was searching for over two weeks now, but i didn't find a solution for my problem.
My problem:
If the user enable/disable iCloud in the settings or change the iCloud account my app should merge the changes in both ways.
So here are my scenarios:
App starts -> iCloud is OFF -> Data is saved (local) -> User turns iCloud ON -> local data will be merged to iCloud
App starts -> iCloud is ON -> Data is saved (iCloud) -> User turns iCloud OFF -> iCloud data will be merged to local
In many other threads some developers wrote, that it is enough to have only ONE persistent store with same options and url, because since iOS 7 core data handles an automatic fallback store if iCloud is disabled and trigger the merge if it is available again. But that doesn't work for me.
Here are some code snippets:
- (NSURL*)storeURL{
NSURL* documentsDirectory = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL];
return [documentsDirectory URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.sqlite",coreDataFileName]];
}
- (NSURL*)modelURL{
return [[NSBundle mainBundle] URLForResource:coreDataFileName withExtension:@"momd"];
}
-(NSMutableDictionary*)getICloudPersistentStoreOptions{
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:
NSInferMappingModelAutomaticallyOption];
//if(self.hasICloudAccountOnDevice & self.iCloudLokalIsAvailable){
[options setObject:@"iCloudStore" forKey:NSPersistentStoreUbiquitousContentNameKey];
//}
return options;
}
- (NSManagedObjectContext *)managedObjectContext{
if (masterContext != nil){
return masterContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil){
masterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
masterContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
[masterContext setPersistentStoreCoordinator: coordinator];
}
return masterContext;
}
- (NSManagedObjectModel *)managedObjectModel{
if (managedObjectModel != nil){
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL];
return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{
if((persistentStoreCoordinator != nil)){
return persistentStoreCoordinator;
}
[self createPersistentStoreCoordinator];
return persistentStoreCoordinator;
}
-(void)createPersistentStoreCoordinator{
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSPersistentStoreCoordinator *psc = persistentStoreCoordinator;
// iCloud notification subscriptions
NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
[dc addObserver:self
selector:@selector(storesWillChange:)
name:NSPersistentStoreCoordinatorStoresWillChangeNotification
object:psc];
[dc addObserver:self
selector:@selector(storesDidChange:)
name:NSPersistentStoreCoordinatorStoresDidChangeNotification
object:psc];
[dc addObserver:self
selector:@selector(persistentStoreDidImportUbiquitousContentChanges:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:psc];
// Set up iCloud persistent store in another thread:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError* error;
[psc lock];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.storeURL
options:[self getICloudPersistentStoreOptions]
error:&error];
[psc unlock];
});
}
in the 'storeWillChange' method i want to implement some deduplication code after NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted but thats another thing.
NSPersistentStoreDidImportUbiquitousContentChangesNotification is currently not used (i think it is only called if an other device saves also some data to iCloud
.
And 'storeDidChange' from NSPersistentStoreCoordinatorStoresDidChangeNotification is called on every app start. So currently i no idea what i should do there.
As i wrote before this doesn't work for me, if i enable or disable iCloud the data won't be merged.
Please help me - Are my thoughts wrong??