Search code examples
objective-cioscore-datapersistenceicloud

How can I migrate the data from the iCloud store file to a new store file in local storage?


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?


Solution

  • 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.