2
votes

I try to sync core data between IOS and OSX. At both apps I have the same configuration:

enter image description here

And the same entitlements:

enter image description here

I also use the same code for the store coordinator within the same name for sqlite file and url:

NSManagedObjectModel* managedModel = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator* storeCooordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedModel];

//-> start iCloud
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{


        NSURL* applicationFilesDirectory = [JHDCoreDataDAO applicationFilesDirectory];
        NSURL* storeURL = [applicationFilesDirectory URLByAppendingPathComponent:DATABASE_NAME];

        if(!storeURL) { NSLog(@"Error reading applicationFilesDirectory for given sqlite resouce"); }

        NSString* containerIdentifier = [NSString stringWithFormat:@"%@.%@",TEAM_IDENTIFIER,APP_IDENTIFIER];
        NSURL* iCloud = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:containerIdentifier];

        NSString *iCloudEnabledAppID = @"TEAMID~com~sample~sample";
        NSError* persistentStoreError;

        if (iCloud) {

            NSLog(@"iCloud is working");
            NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
            NSLog(@"iCloud URL: %@",iCloud);

            NSString* cloudPath = [[iCloud path] stringByAppendingPathComponent:@"data"];
            NSURL* transactionsLogUrl = [NSURL fileURLWithPath:cloudPath];

            NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:
                                     iCloudEnabledAppID, NSPersistentStoreUbiquitousContentNameKey,
                                     transactionsLogUrl, NSPersistentStoreUbiquitousContentURLKey,
                                     [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                 nil];

        [storeCooordinator lock];
        if(![storeCooordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL  options:options error:&persistentStoreError])
        {
            NSLog(@"Fehler: %@, %@", persistentStoreError.localizedDescription, persistentStoreError.userInfo);
            abort();
        }
        [storeCooordinator unlock];

    } else {
    //Handle local psc
    }
});

Each app, the IOS Version and the OSX Version, are still running perfectly within the iCloud. Each app handle its own database, due to there is no sync between this two apps. Is there somethings what I have forgotton?

1
Why are you using the AppID for the NSPersistentStoreUbiquitousContentNameKey ? Presumably the iOS app AppID and the OS X app AppID are not the same or is this actually hardcoded in the real apps ? In any event the NSPersistentStoreUbiquitousContentNameKey and the iCloud containerID must be identical for all apps wanting to sync the same Core Data store. Your ubiquity container in the Xcode is sample.sample.sample and in your code its `com.sample.sample'Duncan Groenewald
I have a similar problem. When i try to sync with iCloud in my os x app i get this error: __60-[PFUbiquitySetupAssistant canReadFromUbiquityRootLocation:]_block_invoke690(1489): CoreData: Ubiquity: Attempting to download Peers hit a serious error for peers to download Error Domain=BRCloudDocsErrorDomain Code=5 "(BRCloudDocsErrorDomain 5: No document at URL)"user3065901

1 Answers

3
votes

You need to be very careful that the identifiers you use in the entitlements match what you use in the source code to access the ubiquity container.

One complication when syncing multiple apps (e.g. Mac app and iOS app) is that you will need to check that they each have the same team identifier. If not, you will want to fill in the team id explicitly for iCloud entitlements, rather than using the TeamIdentifierPrefix variable. Pick one of the team ids and use that for both apps.

In your particular example, it looks like you have entitlements setup for a container id that ends in sample.sample.sample. Assuming the team id is the same for each app, your container id should be XXXXXXXXXX.sample.sample.sample, where the first part is your team id. I don't know what APP_IDENTIFIER is in this instance, but it should be checked to make sure it is sample.sample.sample. (My guess is that it isn't.)

The NSPersistentStoreUbiquitousContentNameKey setting can be basically any label you like for your store. It doesn't have to use the ~ or even be reverse-DNS form. For example, you could call it 'Store1'.

I find the easiest way to see if everything is setup OK is to go to the ~/Library/Mobile Documents folder on your Mac, and look for the app container. You can just browse the contents directly in Finder.

Unfortunately, this is probably the easiest part of getting Core Data working with iCloud. There will be many more hurdles, and they tend to be more challenging. There are new solutions coming up for syncing Core Data all the time, including the TICDS framework and Core Data Ensembles, both of which work with iCloud. (Disclosure: I have contributed to both projects, and founded the Ensembles project.)