Question

I have a simple application out in the App Store which is a UITableView which is populated by the user filling in some UITextFields in a view that's called up modally. The user presses save and everything goes saved to Core Data and using NSFetchedResultsControllers, the UITableView is updated.

I am now updating my application to introduce iCloud synching (and an iPad version).

I'm new to iCloud development and although the post I followed http://goddess-gate.com/dc2/index.php/post/452 is a few years old, it mostly works for me.

Problem

Without going further into other issues, the one issue I'm having right now is the fact that if I'm running the App Store version of my app with some data (which doesn't have iCloud enabled), when I update my app using my development build in Xcode, I'm expecting my original data to still be there and to therefore upload to iCloud.

I don't have a check box in my app saying don't upload, but I will get to that. For now, the problem is I'm starting with a completely blank database when I update my app, though I suspect it's just a problem with my code actually showing the data now because in the settings of my device, it's showing 9.7 KB of data stored in iCloud (I made sure to remove the iCloud backup data before doing this test).

I've adjusted my App Id in the Developer Portal to include iCloud and adjusted Xcode to include that, while creating a new SSL certificate in the Developer and important the new provisioning profiles into Xcode.

Update: Made a lot of changes to my app and removing old code

Here's my App Delegate persistentStoreCoordinator code: (following the advice from Tom's answer)

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Planner.sqlite"];
    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSDictionary *options = @{
                              NSMigratePersistentStoresAutomaticallyOption : @YES,
                              NSInferMappingModelAutomaticallyOption : @YES
                              };
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    NSPersistentStore *ps = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];

    NSFileManager *fm = [NSFileManager defaultManager];
    NSURL *url = [fm URLForUbiquityContainerIdentifier:nil];
    NSDictionary *iCloudOptions = @{
                              NSMigratePersistentStoresAutomaticallyOption : @YES,
                              NSInferMappingModelAutomaticallyOption : @YES,
                              NSPersistentStoreUbiquitousContentNameKey : @"EnvysStore"
                              };
    NSPersistentStore *store = [[_persistentStoreCoordinator persistentStores] firstObject];

    store = [_persistentStoreCoordinator migratePersistentStore:ps toURL:url options:iCloudOptions withType:NSSQLiteStoreType error:&error];

    return _persistentStoreCoordinator;
}

However, upon running my app, the app crashes with :

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'nil is not a valid persistent store' on the 

    store = [_persistentStoreCoordinator migratePersistentStore:ps toURL:url options:iCloudOptions withType:NSSQLiteStoreType error:&error];

Problem

So the problem is, when I have the app Store version of my app with some data and then update to this version, firstly the app crashes as above, but once I get that fixed, I want my existing data to be migrated to the cloud.

Any guidance on this would be massively appreciated!

Was it helpful?

Solution

Without going further into other issues, the one issue I'm having right now is the fact that if I'm running the App Store version of my app with some data (which doesn't have iCloud enabled), when I update my app using my development build in Xcode, I'm expecting my original data to still be there and to therefore upload to iCloud.

It's not that simple. Core Data's iCloud integration uses transaction logs to sync changes. Transaction logs are generated every time you save changes to the persistent store file. If you just add iCloud support while existing data is present, no transactions are generated for that data. No transaction logs, no sync, and your data remains local.

To move existing data to iCloud you need to migrate the persistent store to a new file, in the process generating transactions for all of that existing data. The easiest way to do this is by calling [NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:], which takes the same options as you use when adding a persistent store file. Migrate your local store to a new iCloud-enabled store and, if everything is working, you'll get transaction logs and the data will upload.

If your persistent stores are very large, you may need to use custom migration code. Most of the time though, the built-in migration method is just fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top