Based on the question here: Migrate iCloud data to Local store and stopping iCloud from still responding regard moving an iCloud store over to a local store and making sure the iCloud notifications are disabled, I have the next scenario that I am stuck on.
Issue
Right now, when the user runs the app on the first device, they're asked at the start if they want to enable iCloud. If they select yes, the data is migrated over to iCloud. If the user connects in a second device, they're asked if they want to use iCloud at the start and if they select yes, data from the first device is synchronised across.
If the user on the second device decides they don't want to use iCloud anymore, they can navigate and turn off iCloud within the app for that device specifically. This in the back-end will migrate their data from the iCloud store to the Local Store. From the users point of view, all of their data is there (whether it's stored in the cloud or local doesn't matter to the user at this point).
The issue is when I migrate my data across, it successfully migrates over to the local iCloud store and successfully stops listening for iCloud notifications. That aspect works and that's in the stack overflow question that I previously asked (Migrate iCloud data to Local store and stopping iCloud from still responding).
The specific issue is that when the user re-launches the app, the app is now empty with no data. This is of course not the desired effect.
For completeness, the "migration code" is based in the other stack overflow question but I'm pasting it here for convenience:
- (void)migrateiCloudStoreToLocalStore {
NSLog(@"Migrate iCloudToLocalStore");
NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores.lastObject;
//NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];
NSURL *storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
NSLog(@"Current Store URL (before iCloud to Local migration): %@", [storeURL description]);
NSDictionary *localStoreOptions = nil;
localStoreOptions = @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES,
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
NSPersistentStore *newStore = [self.persistentStoreCoordinator migratePersistentStore:store
toURL:storeURL
options:localStoreOptions
withType:NSSQLiteStoreType error:nil];
[self reloadStore:newStore];
}
- (void)reloadStore:(NSPersistentStore *)store {
NSLog(@"Reload Store");
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];
NSDictionary *localStoreOptions = nil;
localStoreOptions = @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES,
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
if (store) {
[self.persistentStoreCoordinator removePersistentStore:store error:nil];
}
[self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:localStoreOptions
error:nil];
storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
NSLog(@"Current Store URL (after iCloud to Local migration): %@", [storeURL description]);
NSLog(@"Done reloading");
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:@"MigratedFromiCloudToLocal"];
[[NSUserDefaults standardUserDefaults]synchronize];
All of the magic happens in the persistentStoreCoordinator.. it's messy, but I need to get this part working and then this can be cleaned up:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];
NSError *error = nil;
NSURL *iCloud = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil];
NSDictionary *options = nil;
if ((iCloud) && (![[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && (![[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]))
{
NSLog(@"In the persistent store, iCloud is enabled in the app device but not yet in the app and not on the latest version");
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
}
else if ((iCloud) && ([[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]))
{
NSLog(@"In the persistent store, iCloud is enabled, we're using iCloud from the Tutorial and we're on the latest version");
NSURL *cloudURL = [self grabCloudPath:@"iCloud"];
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentURLKey: cloudURL, NSPersistentStoreUbiquitousContentNameKey: @"EnvyCloud"};
}
else if ((iCloud) && (![[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]))
{
NSLog(@"In the persistent store, iCloud is enabled, we're on the latest version, btu we're not using icloud in the App");
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
}
else
{
NSLog(@"iCloud is just not enabled");
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
}
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
//abort();
}
return _persistentStoreCoordinator;
}
So in the scenario where the user enables iCloud in the app and then decides NOT to have iCloud anymore on this particular device, the iCloud notifications get removed, the store is migrated from the iCloud Store to the local store and a NSUserDefaults is set. On the next launch of the app.. the 3rd if statement evaluates as true in the persistentStoreCoordinator
which is correctly saying we're on the latest version, iCloud is enabled (in the device) but not in the app, but then it shows the app with absolutely no entries whatsoever, kind of like starting fresh.
How do I overcome this and return the store that was just recently migrated?
Any thoughts would seriously be greatly appreciated.