如何创建CoreData状态的快照?

时间:2019-01-04 16:11:56

标签: ios swift core-data

背景故事

我正在开发一个大型iOS应用。这个程序在特定的假设下工作。它们的主要目的是应用程序应与内部存储脱机工作,内部存储是服务器上保存的数据的最后同步状态的快照。我决定使用CoreData来处理此存储。每次启动应用程序时,我都会检查是否启用了WiFi连接,然后尝试将存储与服务器同步。由于数据量大,同步大约需要3分钟。

同步过程包括几个阶段,在每个阶段中,我:

  • 从服务器(XML)获取一些数据
  • 反序列化
  • 将其保存在核心数据中

问题

由于多种原因(互联网连接,服务器关闭,用户离开应用程序等),可以中断同步过程。这可能会导致数据不同步。

让我们假设同步过程有5个阶段,并且在第三个阶段之后中断。结果导致内部存储中有3/5的数据被更新,其余数据不同步。我不允许这样做,因为数据彼此之间紧密相连(业务逻辑)。

目标

我不知道是否可能,但我正在考虑实施一种解决方案。在同步过程开始时,我想创建Core Date当前状态的快照(某种副本),并在同步过程中对其进行操作。同步过程成功完成后,此快照可能会覆盖当前的CoreData状态。当同步中断时,快照可以简单地中止。我的内部存储空间将得到保护。

问题

  • 如何创建CoreData快照?
  • 如何使用CoreData快照?
  • 如何用快照覆盖CoreDate状态?

感谢您的帮助。如果可能,将提供代码示例。

修改1

数据太大,无法使用多个CoreData上下文来处理。在同步期间,我多次将当前上下文保存到清理内存。如果我不这样做,该应用程序将因内存错误而崩溃。

我认为应该使用多个NSPersistentStoreCoordinator来解决,例如使用以下方法:link。不幸的是,我不知道该如何实现。

3 个答案:

答案 0 :(得分:0)

您应该按照您所说的去做。只需使用方法“ load”,“ sync”和“ save”创建类(将其称为SyncBuffer)即可。

“ load”方法应从CoreData中读取所有实体,并将其存储在类变量中。 “ sync”方法应使用类变量进行所有同步。 最后,“保存”方法应将类变量中的所有值保存到CoreData中-在这里您甚至可以从CoreData中删除所有数据,并从SyncBuffer中保存全新的值。

答案 1 :(得分:0)

CoreData堆栈的核心由三个组件组成:上下文(NSManagedObjectContext),模型(NSManagedObjectModel)和存储协调器(NSPersistentStoreCoordinator / NSPersistentStore)。

您想要的是拥有两个不同的上下文,它们共享相同的模型,但是使用两个不同的商店。存储本身将具有相同的类型(即SQLite数据库),但使用不同的源文件。

在此页面上,您可以看到有关堆栈的一些文档:

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html#//apple_ref/doc/uid/TP40001075-CH4-SW1

NSPersistentContainer是用于初始化CoreData堆栈的便捷类。

以链接中的NSPersistentContainer初始化为例:您可以使用完全相同的代码进行初始化,两次,但唯一的区别是两个NSPersistentContainer使用 a不同的.sqlite文件:即,您可以在应用程序委托中有两个属性,分别称为ManagedObjectContextForUI和ManagedObjectContextForSyncing,用于加载不同的.sqlite文件。然后,在您的程序中,您可以使用一个存储中的上下文来获取当前数据以显示给用户,如果您执行同步操作,则可以使用将另一存储与另一个.sqlite一起使用的上下文。 。最终完成同步操作后,您可以最终交换两个文件,并在清除并重新加载NSPersistentContainer之后(这可能很棘手,因为您将要使所有托管对象无效并重新加载:您正在切换到全新的上下文),您可以然后将新同步的数据显示给用户,然后开始在新的.sqlite文件上再次同步

答案 2 :(得分:0)

我理解问题的方式是您希望能够下载大型“对象图”。但是,它太大了,无法立即将其加载到内存中,因此您必须将其拆分成块,然后将其本地合并到Core数据中。

如果是这样,我认为这并非微不足道。我不确定我是否可以在不了解对象关系的情况下想到直接解决方案,即使那样也可能会令人难以承受。

一个过于简单的解决方案可能是在后端生成sqlite文件,然后分块下载;看起来很丑陋,但是它可以将业务逻辑与同步分开,即sqlite文件成为传输层。因此,我认为该解决方案的实质是找到一种方法,以一种物理方式表示要同步的数据,该格式允许将其拆分为多个块,然后可以合并为一个sqlite文件(如果您坚持使用Core数据)。

还请注意,据我所知,Amazon(https://aws.amazon.com/appsync/)和Realm(https://realm.io/blog/introducing-realm-mobile-platform/)为您提供本地数据库的后台同步,但是这些是付费服务,因此您必须注意不要被锁定(不应依赖于模型层中的库,而应具有转换层)。