将部分核心数据保存到云端

Posted

技术标签:

【中文标题】将部分核心数据保存到云端【英文标题】:Save part of Core Data into the cloud 【发布时间】:2014-12-01 15:59:59 【问题描述】:

ios 7 上工作时,我必须使用带有多个实体的 Core Data 来调试应用程序。首先,我要求添加 iCloud(而不是云套件)来保存所有数据。但随后,客户意识到他只想将一些实体而不是所有实体保存到云中。

有可能吗?我需要使用几个 NSPersistentStoreCoordinator 吗? (应用程序已经使用了几个 NSManagedObjectContext,每个实体一个)。或者当我收到通知时我可以做点什么:

NSPersistentStoreDidImportUbiquitousContentChangesNotification

并手动执行合并,但我真的不知道如何。

感谢您的帮助。


感谢 Tom Harrington,我创建了 2 个配置:CloudConfiguration 和 LocalConfiguration,并在每个配置中添加了一些实体(link 也对我有帮助)。

然后,我在协调器中添加持久存储:

    // 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);

我的所有实体都只在一个商店中(云或本地)。不同商店中的实体没有任何关系,我只有一个模型。

所以我开始了,我第一次启动我的应用程序,一切似乎都配置得很好。但是,当我在删除应用程序后尝试在另一台设备上或同一台设备上时,我遇到了崩溃,就在得到:Using local storage: 0.

这是崩溃日志:

[_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)

对我来说这听起来很奇怪,因为它发生在合并之前。当然,在使用这两种配置进行测试之前,我会删除云中的所有数据。如果你有任何想法......

【问题讨论】:

【参考方案1】:

不是多个持久存储协调器,而是多个持久存储文件。您可以通过多次调用addPersistentStoreWithType:configuration:URL:options:error: 将多个持久存储添加到同一个协调器。您不必每次都使用相同的选项,因此您可以为一个存储文件使用 iCloud 选项,但为不同的文件保留它们。

但您需要注意以下几点:

    您无法在不同持久存储文件中的对象之间创建关系。如果这是一个问题,请查看获取的属性。它们是使用您提供的谓词透明地获取对象的属性。它们的工作方式有点像单向关系。

    你需要一些方法来告诉 Core Data 哪个存储文件用于新对象。有几种方法可以做到这一点:

    如果您的某些实体可以进入任一持久存储,则每次创建新实例时都需要使用 [NSManagedObjectContext assignObject:toPersistentStore:]。 对于将始终位于同一存储文件中的实体,请查看模型文件的“配置”。这使您可以创建仅包含一些实体的模型的命名子集。添加持久存储文件时使用配置名称。然后,这些实体的所有新实例都会自动转到正确的文件。

附加,基于更新的问题:

如果您已有 iCloud 数据需要使用,则不能只切换到使用配置。现有的 iCloud 事务日志可能包含对不在您的新 iCloud-only 配置中的实体的引用。当它尝试导入该数据时,它会失败,并且您会遇到与您所看到的类似的错误。

如果这个应用程序仍在开发中,我会说删除所有现有的 iCloud 数据并进行配置。如果您需要保留现有的 iCloud 数据,则必须确保当前 iCloud 数据中的所有实体仍然可用。这很可能意味着您不必进行任何配置,而是将对象分配给代码中的一个商店或另一个商店。

【讨论】:

感谢您的帮助,我现在正在尝试:我想存储在不同存储文件中的实体之间没有任何关系。我刚刚创建了 2 个配置。现在我需要测试,我会更新我的问题给你我的反馈。 感谢更新。所以也许我错过了一些东西,因为正如我在编辑的帖子中所说,我在测试新配置之前删除了 iCloud 数据:设置-> iCloud-> 存储和备份-> 管理存储(我的应用程序仍在开发中)。这就是我认为第一次发布不会崩溃的原因。 如果您仍然遇到同样的错误,很明显它正在尝试导入一个它无法识别的实体。这意味着旧数据仍然存在,或者您仍在以某种方式插入云配置不包含的实体实例。这里没有足够的信息比这更具体。 有效!这是我的错误:所有其他人都有一个父实体,但我没有注意到。因此必须在两种配置中都添加它...

以上是关于将部分核心数据保存到云端的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 gdx-gamesvcs 将游戏数据保存到云端?

我应该将所有图像保存到文件服务器以及云端吗?

使用 store.js 存储的数据是不是持久保存到手机?可以备份到云端吗?

如何将文件上传到 AWS 的云端

如何将添加到Google表格单元格中的图像保存到Google云端硬盘?

将文件保存到Google云端硬盘中的共享文件夹