Reputation: 2349
Working on iOS 7, I have to debug an application using Core Data with several entities. First I was asking for adding iCloud (and not cloud kit) to save all the data. But then, the client realized he wanted to save only some entities but not all of them into the cloud.
Is it something possible ? Do I need to use several NSPersistentStoreCoordinator ? (the application already use several NSManagedObjectContext, one per entity). Or maybe I can do something when I receive the notification :
NSPersistentStoreDidImportUbiquitousContentChangesNotification
and manually perform the merge but I really don't know how.
Thanks for your help.
Thanks to Tom Harrington, I created 2 configurations: CloudConfiguration and LocalConfiguration and I add some entities in each (this link helps me too).
Then, I add persistent store in the coordinator:
// Configure persistentStoreCoordinator
NSError* error1 = nil;
NSString *cloudConfiguration = @"CloudConfiguration";
NSPersistentStore *store1 = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:@"CloudConfiguration"
URL:[self storeURLForConfiguration:cloudConfiguration]
options:@{ NSPersistentStoreUbiquitousContentNameKey : @"iCloudStore" }
error:&error1];
if (error1) {
NSLog(@"Error: %@ \n Description : %@ \nUser info : %@", error1, error1.description, error1.userInfo);
}
NSLog(@"*************** cloud store url ************** : %@", store1.URL);
NSError* error2 = nil;
NSString *localConfiguration = @"LocalConfiguration";
NSPersistentStore *localStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:localConfiguration
URL:[self storeURLForConfiguration:localConfiguration]
options:nil
error:&error2];
if (error2) {
NSLog(@"Error: %@ \n Description : %@ \nUser info : %@", error2, error2.description, error2.userInfo);
}
NSLog(@"*************** local store url ************** : %@", localStore.URL);
All of my entities goes in one store only (cloud or local). Entities in different store don't have any relationship and I have a single model.
So here I go, I start my app for the first time all seems to be well configured. But when I try on another device or on the same device after deleting the app, I have a crash, just after getting : Using local storage: 0.
Here is the crash log :
[_PFUbiquityRecordImportOperation main](734): CoreData: Ubiquity: Error importing transaction log: <PFUbiquityTransactionLog: 0x16ed7f50>
transactionLogLocation: <PFUbiquityLocation: 0x16ed7ee0>: /var/mobile/Library/Mobile Documents/6ULEJ9RYTQ~fr~company~iCloudTestApp/CoreData/iCloudStore/mobile~E722813A-96E8-4E11-8DDE-56FF3837DEBD/iCloudStore/EU31J4aJIvvEyVMcWWYs1qgVajMk4_4fQxw1oe_Q0i0=/4C6B58B3-6C8D-4393-9B1E-8E48C7352091.1.cdt
transactionNumber: 1, exception: Invalid parameter value (bad entity)
User Info: (null)
2014-12-02 12:35:34.837 iCloudTestApp[1421:3b0b] -[_PFUbiquityRecordsImporter discoverAndImportAllAvailableLogs:error:](727): CoreData: Ubiquity: Exception while scanning for logs to import: Invalid parameter value (bad entity)
userInfo: (null)
It sounds weird to me because it's happen before the merge. Of course, I remove all the datas in the cloud before testing with those two configurations. If you have any idea...
Upvotes: 2
Views: 254
Reputation: 70976
Not multiple persistent store coordinators, but multiple persistent store files. You can add multiple persistent stores to the same coordinator by calling addPersistentStoreWithType:configuration:URL:options:error:
multiple times. You don't have to use the same options every time, so you can use iCloud options for one store file but leave them out for a different one.
But you need to be aware of a couple of things:
You can't create relationships between objects in different persistent store files. If that's a problem, look into fetched properties. They're properties that transparently fetch objects using a predicate that you provide. They work sort of like one-way relationships.
You need some way to tell Core Data which store file to use for new objects. There are a couple of ways to do this:
[NSManagedObjectContext assignObject:toPersistentStore:]
every time you create a new instance.Additional, based on updated question:
If you already have iCloud data that you need to use, you can't just switch to using configurations. The existing iCloud transaction logs may contain references to entities that are not in your new iCloud-only configuration. When it tries to import that data, it will fail, and you'll get errors like the one you're seeing.
If this app is still in development, I'd say just delete all existing iCloud data and go with the configuration. If you need to keep the existing iCloud data, you must ensure that all entities in the current iCloud data are still available. That most likely means you'll have to do without configurations and instead assign objects to one store or the other in your code.
Upvotes: 4