从iCloud迁移到Local然后本地再次迁移到iCloud时必须使用新的NSPersistentStoreUbiquitousContentNameKey

时间:2014-08-11 08:43:32

标签: ios core-data icloud appdelegate

我有一个场景,我的应用程序当前在App Store中没有启用iCloud,但随着我正在进行的更新,iCloud将在那里。用户可以在升级后立即选择是否在使用应用程序时立即使用iCloud,并且还可以决定在应用程序内打开/关闭它。

现在,如果用户在开始时选择“是”以使用iCloud,则数据会从App Store版本(非iCloud)迁移到iCloud,并且我可以将数据从iCloud存储迁移回本地存储。用户在应用程序中关闭iCloud。

然而,逻辑会告诉我,如果我想让用户再次在应用程序中打开iCloud,它应该将本地迁移到iCloud存储。

以下是在App Delegate:

中首次运行应用时从非iCloud到iCloud的初始迁移代码
- (void)upgradeAndMigrateCoreDataToiCloud {

    NSLog(@"Just upgraded your app. On the next run, this does not happen again.");

    NSURL *storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
    NSLog(@"Current Store URL (before migration): %@", [storeURL description]);

    NSPersistentStore *currentStore = self.persistentStoreCoordinator.persistentStores.lastObject;

URLByAppendingPathComponent:@"NewStore.sqlite"];
        NSURL *cloudURL = [self grabCloudPath:@"CloudLogs"];
        NSString *cloudStoreTitle = @"EnvyCloud";


    NSDictionary *options = @{NSPersistentStoreUbiquitousContentURLKey: cloudURL,
     NSPersistentStoreUbiquitousContentNameKey: cloudStoreTitle,                               NSMigratePersistentStoresAutomaticallyOption : @YES,
     NSInferMappingModelAutomaticallyOption : @YES};

    [self.persistentStoreCoordinator migratePersistentStore:currentStore toURL:storeURL options:options withType:NSSQLiteStoreType error:nil];

    storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
    NSLog(@"Current Store URL (after migration): %@", [storeURL description]);

}

完美无缺。

以下是用户想要从设置中启用iCloud同步的代码(如果之前关闭的话,或者如果用户将其关闭并且现在想要将其重新打开):

- (void)iCloudHasBeenEnabledFromSettings
{
    NSURL *iCloud = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil];

    if ((iCloud) && ([[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]))
    {
        NSLog(@"iCloud is enabled, and so we can do the migration from the local to iCloud");
        [self iCloudNotifications];

        NSURL *storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
        NSLog(@"Current Store URL (before migration from local to iCloud): %@", [storeURL description]);

        NSPersistentStore *currentStore = self.persistentStoreCoordinator.persistentStores.lastObject;

        NSURL *cloudURL = [self grabCloudPath:@"CloudLogs"];
        NSString *cloudStoreTitle = @"EnvyCloud";

        NSDictionary *options = @{NSPersistentStoreUbiquitousContentURLKey: cloudURL,
                                  NSPersistentStoreUbiquitousContentNameKey: cloudStoreTitle,                               NSMigratePersistentStoresAutomaticallyOption : @YES,
                                  NSInferMappingModelAutomaticallyOption : @YES};

        [self.persistentStoreCoordinator migratePersistentStore:currentStore toURL:storeURL options:options withType:NSSQLiteStoreType error:nil];

        storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
        NSLog(@"Current Store URL (after migration from local to iCloud): %@", [storeURL description]);
    }
    else if (!(iCloud) && ([[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]))

    {
        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"iCloud is Disabled on the Device" message:@"Do you want to turn it on now? If so, you can do this from the device Settings" delegate:self cancelButtonTitle:@"Turn OFF iCloud" otherButtonTitles:@"Settings", nil];
        [alertView show];            
    }
}

这里唯一的区别是我正在重新调用iCloud通知,并且我有一个if语句来检查设备上是否启用了iCloud。

检查NSLog路径的最后一个storeURL是问题所在。

在升级方法中,迁移后的storeURL为:

Current Store URL (after migration): file:///var/mobile/Applications/B07684DE-F74A-4503-A7B3-CD6D82CD087D/Documents/CoreDataUbiquitySupport/mobile~F6322EC0-DA27-4EEB-A6A4-0D3EA875241B/EnvyCloud/3B2005FA-FEEE-4F90-A049-E068B35F09AA/store/Envylope.sqlite

显示已正确迁移。

在第二种方法中,从本地迁移到iCloud之前的当前存储URL是:

Current Store URL (before migration): file:///var/mobile/Applications/B07684DE-F74A-4503-A7B3-CD6D82CD087D/Documents/Envylope.sqlite

问题

问题是迁移后,NSLog仍然是:

Current Store URL (before migration): file:///var/mobile/Applications/B07684DE-F74A-4503-A7B3-CD6D82CD087D/Documents/Envylope.sqlite

在此方法(iCloudHasBeenEnabledFromSettings)中,如果我将NSPersistentStoreUbiquitousContentNameKey更改为略有不同的名称(之前为EnvyCloud并将其更改为例如EnvyCloudNew),则它有效,NSLog向我显示CoreDataUbiquityContainer

当然我做错了,或者它是如何工作的,它不能使用“相同的”NSPersistentStoreUbiquitousContentNameKey?

此外,使用其他NSPersistentStoreUbiquitousContentNameKey

是否存在任何问题

更新

我一直在做很多工作,对这个问题有一些更新,我真的希望有人可以帮忙。

如果我不更改NSPersistentStoreUbiquitousContentNameKey的名称并保持不变,并且如果我通过迁移传递错误参数,则控制台中的输出错误为:

Error = Error Domain=NSCocoaErrorDomain Code=134080 "The operation couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x15e9ae90 {NSUnderlyingException=Can't add the same store twice}

这是有意义的,它不能两次添加相同的商店。

我可以通过首先迁移persistentStore,然后在最终添加一个新的persistentStore之前设置_persistentStoreCoordinator = nil来解决这个问题 - 这是有效的,但同样,这对我来说似乎不对。我需要这样做是没有意义的。如果我选择从本地商店返回到iCloud,为什么我不能从已经存储在iCloud中的内容重建?

我希望此更新有助于指出某人指出我正确的方向。

任何想法都将不胜感激。

0 个答案:

没有答案