I have iCloud
in my app. I've removed iCloud
from my app, but on ios 6 app crashes and I get this message:
-[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:](1055):
CoreData: Ubiquity: Error:
A persistent store which has been previously added to a coordinator using the iCloud integration options must always be added to the coordinator with the options present in the options dictionary. If you wish to use the store without iCloud
, migrate the data from the iCloud
store file to a new store file in local storage.
How can I solve this error? How can I migrate the data from the iCloud
store file to a new store file in local storage?
YES, I have this question too.
I want to turn a iCloud store to a local store
Solution 1 :Moving managedObjects one-by-one to the localStore.
But if you have a large database, it will be so slow.
So I found a second solution yesterday.
Solution 2: Editing the metadata of the iCloud store,
and saving it to the new location.
After you remove "com.apple.coredata.ubiquity.*" keys in metadata,
you'll get a fully local store.
Here is my code for solution 2:
There are some properties already set:
@property (nonatomic, strong) NSPersistentStoreCoordinator *coordinator;
@property (nonatomic, strong) NSManagedObjectContext *context;
@property (nonatomic, strong) NSPersistentStore *iCloudStore;
//represent the iCloud store already using
//(after [coordinator addPersistentStore] you get this NSPersistentStore)
@property (nonatomic, strong) NSURL *iCloudStoreURL;
//represent the iCloud store real location
//(it is the URL you send to the [coordinator addPersistentStore])
@property (nonatomic, strong) NSURL *iCloudStoreLocalVersionURL;
//represent the location of local version store you want to save
And the migrate method:
-(void)migrateCloudStoreToLocalVersion
{
if(!self.iCloudStore)
return;
// remove previous local version
[FILE_MANAGER removeItemAtURL:self.iCloudStoreLocalVersionURL
error:nil];
// made a copy from original location to the new location
[FILE_MANAGER copyItemAtURL:self.iCloudStoreURL
toURL:self.iCloudStoreLocalVersionURL
error:nil];
//prepare meta data
NSDictionary *iCloudMetadata = [self.coordinator metadataForPersistentStore:self.iCloudStore].copy;
NSMutableDictionary *localVersionMetadata = iCloudMetadata.mutableCopy;
for(NSString * key in iCloudMetadata){
if([key hasPrefix:@"com.apple.coredata.ubiquity"]){
[localVersionMetadata removeObjectForKey:key];
}
}
//modify iCloud store
[self.coordinator setMetadata:localVersionMetadata forPersistentStore:self.iCloudStore];
[self.coordinator setURL:self.iCloudStoreLocalVersionURL forPersistentStore:self.iCloudStore];
//save to the localVersion location
[self.context save:nil];
//restore iCloud store
[self.coordinator setMetadata:iCloudMetadata forPersistentStore:self.iCloudStore];
[self.coordinator setURL:self.iCloudStoreURL forPersistentStore:self.iCloudStore];
}
Then you can use the iCloudStoreLocalVersionURL
to using the local version store.
You can use this local version store as local store, without any error.
Note:
Notice the NSStoreUUIDKey
in the metadata,
you can optional replace it for the new store.
I believe you have to change out the UUID number too, I would get errors on the next run of the app that it was loading the same store twice. so i made this modification
if (!self.iCloudStore) return;
NSError *error = nil;
NSURL* localStoreURL = [self fallbackStoreURL];
NSFileManager *fm = [[NSFileManager alloc] init];
if (!self.fallbackStore) [self loadFallbackStore:&error];
NSString* fallBackUUID;
//find UUID of original to put back in later
NSDictionary *fallBackMetadata = [_psc metadataForPersistentStore:self.fallbackStore].copy;
for(NSString* key in fallBackMetadata)
{
if([key hasPrefix:@"NSStoreUUID"])
{
fallBackUUID = [fallBackMetadata objectForKey:key];
break;
}
}
[fm removeItemAtURL:localStoreURL error:nil];
//prepare meta data
NSDictionary *iCloudMetadata = [_psc metadataForPersistentStore:self.iCloudStore].copy;
NSMutableDictionary *localVersionMetadata = iCloudMetadata.mutableCopy;
for(NSString* key in iCloudMetadata)
{
if([key hasPrefix:@"com.apple.coredata.ubiquity"])
{
[localVersionMetadata removeObjectForKey:key];
}
if([key hasPrefix:@"NSStoreUUID"])
{
if (fallBackUUID) [localVersionMetadata setObject:fallBackUUID forKey:key];
}
}
//modify iCloud store
[_psc setMetadata:localVersionMetadata forPersistentStore:self.iCloudStore];
[_psc setURL:localStoreURL forPersistentStore:self.iCloudStore];
// make a copy from original location to the new location
[fm copyItemAtURL:[self iCloudStoreURL]
toURL:localStoreURL
error:nil];
[_fallbackContext save:nil];
[_psc setMetadata:iCloudMetadata forPersistentStore:self.iCloudStore];
[_psc setURL:[self iCloudStoreURL] forPersistentStore:self.iCloudStore];