【问题标题】:Snapshots of data in iCloud enabled Core Data app?启用 iCloud 的 Core Data 应用程序中的数据快照?
【发布时间】:2014-01-13 23:25:25
【问题描述】:

我的应用通过 iCloud 同步和备份其数据(为此我使用了iCloudCoreDataStack)。当我的应用程序处理用户创建的重要数据时,我想通过不时创建快照的能力来提供额外的安全网,这些快照可以在以后恢复。

我不是在谈论撤消一两个单个更改,而是关于真实快照、时间戳和以保存方式存储。

由于我正在利用 iCloud 同步,我不能简单地交换应用程序中使用的 sqlite 商店。我想我必须删除当前上下文中的每个对象,创建从快照恢复的对象并保存上下文。然后,设备也会将更改推送到 iCloud。

我正在考虑以下场景:

  1. 该应用可以正常运行,但没有创建快照的选项(这只是用户的一项可选安全功能)。
  2. 如果用户不时选择创建快照,系统会要求他输入 Dropbox 登录凭据(已实现)。
  3. 我的应用程序有时会创建一个后台线程,其中将设置第二个商店和第二个 MOC(以及第二个 PSC?)。每个对象及其关系都被复制到第二个 MOC 中。第二个 MOC 被保存,持久存储将被复制到 Dropbox,线程将结束。
  4. 如果用户想要恢复快照并放弃创建快照后所做的所有更改,我的应用将通过反向执行第 3 点中所述的操作来重建数据。

对此有什么想法吗?这是要保存的吗,是否需要考虑任何警告(尤其是与 iCloud 一起)?有没有人以类似的方式做到这一点?


编辑:

我通过上述步骤成功创建了商店的副本。在第一次尝试中,商店的娱乐活动似乎也奏效了。但是,我仍然担心我加载存储文件的方式(将旧文件拉走,然后用我保存的文件替换它)。

但是,我遇到过 Apple 的“另存为...”或“重新定位”方法

NSDictionary *options = @{
    NSPersistentStoreRemoveUbiquitousMetadataOption: @YES
};
NSPersistentStore *copy = [psc migratePersistentStore:currentiCloudStore
                                                toURL:url
                                              options:options
                                             withType:NSSQLiteStoreType
                                                error:&error];

这将删除所有与 iCloud 相关的元数据,并从协调器中删除当前存储(我不希望这样做)并将新创建的存储添加到 PSC(我也不希望这样做)。

什么是更好的方法?我当前的方法还是 Apples 内置的“另存为.../重新定位”?我的重点是稍后加载快照,无论是否启用/启用了 iCloud。

【问题讨论】:

    标签: core-data icloud snapshot


    【解决方案1】:

    在创建备份存储时,请注意,有报告称 migratePersistentStore 会破坏所有多对多关系,而不会出现任何错误或表明它正在这样做。我使用 migratePersistentStore 在我的应用程序中有一个备份功能(通过 Bonjour 共享一个类似的功能),并开始获取一些丢失数据的用户报告。虽然上述解决方案可行,但您可能会默默地丢失数据。或者,如果您的方案中没有任何多对多关系,则希望您会没事。 “备份”功能的感觉不是很好,对吧?

    我为此苦苦挣扎了好几天,直到我在 https://devforums.apple.com/message/1055235#1055235 找到了 Ivan Pavlov 的帖子,他在此提交了雷达 18480943。

    总而言之,如果您的架构具有多对多关系,我不会使用 migratePersistentStore,除非您在迁移后也返回并手动重新创建这些关系中的所有链接。

    【讨论】:

      【解决方案2】:

      我也一直在寻找一种允许我的用户执行备份快照的解决方案。我无法使用 migratePersistentStore,因为它在此过程中删除了我的活动商店。然后我想知道是否可以将商店添加到不同的 PSC,然后迁移它,从而保持原始 PSC 不变。此备份代码似乎可以在不中断我的实时堆栈的情况下工作。不过,我有点不确定是否要向 2 个 PSC 添加商店。

      - (void)backupStore {//saves the store to backup.sqlite
      
          NSFileManager *fm = [[NSFileManager alloc] init];
          NSError *localError = nil;
          _ubiquityURL = [fm URLForUbiquityContainerIdentifier:nil];
          NSURL *backupStoreURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"backupStore.sqlite"]];
          NSURL *iCloudStoreURL = [self iCloudStoreURL];
          NSMutableDictionary *options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithBool:YES],     NSMigratePersistentStoresAutomaticallyOption,
                                      [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                      nil];
         [options setObject:@"Logbook" forKey:NSPersistentStoreUbiquitousContentNameKey];
       //Add the store to tempPSC
         NSPersistentStoreCoordinator *tempPSC = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
          NSPersistentStore *store = [tempPSC addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:iCloudStoreURL options:options error:&localError];
         //migrate the store to local database
          options = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],   NSPersistentStoreRemoveUbiquitousMetadataOption,nil];
          if ([tempPSC migratePersistentStore:store toURL:backupStoreURL options:options withType:NSSQLiteStoreType error:&localError]) {
              NSLog(@"migratePersistentStore did it!!");
          } else {
              NSLog(@"migratePersistentStore failed!!...%@",localError);
          }
      
      }
      

      【讨论】:

      • 感谢您的接近。我已经向 Apple 申请了 TSI,并在我收到他们的回复时告诉你他们说了什么。
      • TSI 回复是否说可以将其包含在运输应用程序中?
      【解决方案3】:

      我目前允许用户使用 File Save As 菜单选项在 OS X 上创建任何 Core Data 文件的备份副本,这使用 migratePersistentStore API 创建没有 iCloud 选项的新副本。当然,如果文件尚未存储在 iCloud 中,则无需这样做,用户只需使用文件管理器复制文件即可。在 iOS 设备上,您将使用相同的方法,除了您需要编写自己的文件管理器来复制任何文件,因此使用 migratePersistentStore API 创建新文件可能更容易。为了恢复您需要将其迁移到 iCloud 的文件,您不能只是将其复制回来。看看这个链接,我已经发布了一些解释和示例代码以及一些视频,展示了当使用更改其 iCloud 首选项设置时文件如何移入和移出 iCloud。此应用是基于文档的应用,因此允许创建多个文档,只需在 FileListViewController 上添加一个弹出菜单即可将备份文件制作到您选择的位置。

      http://ossh.com.au/design-and-technology/software-development/uimanageddocument-icloud-integration/

      【讨论】:

        【解决方案4】:

        您的基本方法在我看来不错。我也在使用 iCloudCoreDataStack,我认为这是一个强大的解决方案。

        如果您想保存新商店,我不明白您为什么要遍历所有对象并重新创建它们。只需保存所有,锁定商店,制作本地副本,解锁商店(用户现在可以继续工作),然后将商店复制到 DropBox。还原时,用下载的存储覆盖现有存储(如果在同一设备上且沙盒仍然存在,则无需下载)。此时,您可能还需要重置 iCloud 商店。

        话虽如此,如果您已经在遍历对象图,您可能会使用它来做一些可能会变得有用的额外事情。您可以将整个对象图转换为 JSON 并将其存储为文本文件(如果没有可转换或二进制属性)。您的数据现在可以通过更多方式和更多平台进行人类阅读和使用。

        【讨论】:

        • 谢谢,我做到了。对我对 Apple 内置“重定位”方法的编辑有何想法?
        猜你喜欢
        • 1970-01-01
        • 2015-10-04
        • 1970-01-01
        • 2015-04-09
        • 2011-12-07
        • 2015-04-04
        • 2011-12-14
        • 2012-12-15
        • 1970-01-01
        相关资源
        最近更新 更多