如何同步iPhone核心数据与web服务器,然后推到其他设备?

我一直在研究一种方法,在多个设备(如iPad或Mac)之间同步存储在iPhone应用程序中的核心数据。在iOS上,用于core data的同步框架并不多(如果有的话)。然而,我一直在思考以下概念:

  1. 对本地核心数据存储进行更改,并保存更改。(a)如果设备在线,它尝试向服务器发送更改集,包括发送更改集的设备的设备ID。(b)如果更改集没有到达服务器,或者如果设备没有在线,应用程序将把更改集添加到队列中,当它在线时发送。
  2. 位于云中的服务器将接收到的特定更改集与其主数据库合并。
  3. 在云服务器上合并更改集(或更改集队列)之后,服务器使用某种轮询系统将所有这些更改集推到注册到服务器的其他设备。(我想使用苹果的Push服务,但根据评论,这显然不是一个可行的系统。)

有什么特别的需要我考虑的吗?我已经看过REST框架,如ObjectiveResource核心资源RestfulCoreData。当然,这些都是与Ruby on Rails一起工作的,我并不依赖于Ruby on Rails,但这是一个起点。我的解决方案的主要要求是:

  1. 任何更改都应该在后台发送,而不需要暂停主线程。
  2. 它应该使用尽可能少的带宽。

我想过一些挑战:

  1. 请确保服务器上挂载了不同设备上不同数据存储的对象id。也就是说,我将有一个对象id和设备id的表,它们通过对存储在数据库中的对象的引用进行绑定。我将有一个记录(DatabaseId[唯一的这个表],ObjectId[唯一的项目在整个数据库],Datafield1, Datafield2), ObjectId字段将引用另一个表,AllObjects:(ObjectId, DeviceId, DeviceObjectId)。然后,当设备上推一个更改集时,它将沿着来自本地数据存储中的核心数据对象的设备Id和objectId传递。然后,我的云服务器将检查AllObjects表中的objectId和设备Id,并在初始表中找到要更改的记录。
  2. 所有的更改都应该有时间戳,这样它们就可以合并。
  3. 该设备将不得不轮询服务器,而不会消耗太多电池。
  4. 如果/当从服务器接收到更改时,本地设备还需要更新存储在内存中的任何内容。

我还遗漏了什么吗?我应该考虑什么样的框架来实现这一点?

90083 次浏览
通过推送通知通知用户更新数据。 在应用程序中使用后台线程来检查本地数据和云服务器上的数据,当服务器发生变化时,更改本地数据,反之亦然

所以我认为最困难的部分是估计哪一方的数据是无效的。

希望这能对你有所帮助

我做过和你想做的类似的事。让我告诉你我学到了什么以及我是怎么做的。

我假设您的Core Data对象和服务器上的模型(或db模式)之间有一对一的关系。您只是想让服务器内容与客户机保持同步,但是客户机也可以修改和添加数据。如果我没猜错,那就继续读下去。

我添加了四个字段来帮助同步:

  1. sync_status -只添加这个字段到你的核心数据模型。应用程序使用它来确定你是否对项目有待处理的更改。我使用以下代码:0表示没有更改,1表示它正在排队等待同步到服务器,2表示它是一个临时对象,可以被清除。
  2. is_deleted -添加到服务器和核心数据模型。Delete事件实际上不应该从数据库或客户端模型中删除一行,因为它使您没有任何东西可以进行同步。通过使用这个简单的布尔标志,您可以将is_deleted设置为1,并同步它,所有人都会满意。您还必须修改服务器和客户端上的代码,以查询带有“is_deleted=0”的未删除项。
  3. last_modified -添加到服务器和核心数据模型。当该记录上有任何更改时,服务器应该自动使用当前日期和时间更新该字段。客户端不应该修改它。
  4. guid -为服务器和核心数据模型添加一个全局唯一id(参见http://en.wikipedia.org/wiki/Globally_unique_identifier)字段。该字段成为主键,在客户端上创建新记录时变得非常重要。通常情况下,主键在服务器上是一个递增的整数,但我们必须记住,内容可以离线创建并在以后同步。GUID允许我们在脱机时创建一个键。

在客户机上,添加代码,在您的模型对象上设置sync_status为1,当某些内容发生变化并需要同步到服务器时。新的模型对象必须生成一个GUID。

同步是一个单独的请求。该请求包括:

  • 模型对象的MAX last_modified时间戳。这告诉服务器您只希望在此时间戳之后进行更改。
  • 包含sync_status=1的所有项的JSON数组。

服务器获得请求并执行以下操作:

  • 它从JSON数组中获取内容,并修改或添加其中包含的记录。last_modified字段会自动更新。
  • 服务器返回一个JSON数组,其中包含所有last_modified时间戳大于请求中发送的时间戳的对象。这将包括它刚刚接收到的对象,这将作为记录成功同步到服务器的确认。

应用程序接收响应并执行以下操作:

  • 它从JSON数组中获取内容,并修改或添加其中包含的记录。每条记录的sync_status设置为0。

我希望这对你有所帮助。我交替使用了“记录”和“模型”这两个词,但我认为您已经明白了这个意思。祝你好运。

我建议仔细阅读并执行Dan Grover在iPhone 2009会议上讨论的同步策略,可获得在这里作为pdf文档。

这是一个可行的解决方案,实现起来并不难(Dan在它的几个应用程序中实现了它),与Chris描述的解决方案重叠。关于同步的深入理论讨论,请参阅Russ Cox(麻省理工学院)和William Josephson(普林斯顿大学)的论文:

矢量时间对文件同步 . 在这里获得

由Marcus Zarra开发的名为ZSync的Objective-C框架已经弃用,因为iCloud似乎终于支持正确的核心数据同步了。

如果你还在寻找一种方法,可以看看Couchbase手机。这基本上就是你想要的。(http://www.couchbase.com/nosql-databases/couchbase-mobile)

我刚刚发布了我的新核心数据云同步API的第一个版本,称为SynCloud。 SynCloud与iCloud有很多不同,因为它允许多用户同步界面。它也不同于其他同步api,因为它允许多表,关系数据

请在http://www.syncloudapi.com找到更多信息

使用iOS 6 SDK构建,它是2012年9月27日的最新版本。

类似于@Cris,我已经实现了客户端和服务器之间的同步类,并解决了迄今为止所有已知的问题(向服务器发送/接收数据,基于时间戳合并冲突,在不可靠的网络条件下删除重复条目,同步嵌套数据和文件等。)

您只需告诉类应该同步哪个实体和哪些列,以及服务器在哪里。

M3Synchronization * syncEntity = [[M3Synchronization alloc] initForClass: @"Car"
andContext: context
andServerUrl: kWebsiteUrl
andServerReceiverScriptName: kServerReceiverScript
andServerFetcherScriptName: kServerFetcherScript
ansSyncedTableFields:@[@"licenceNumber", @"manufacturer", @"model"]
andUniqueTableFields:@[@"licenceNumber"]];




syncEntity.delegate = self; // delegate should implement onComplete and onError methods
syncEntity.additionalPostParamsDictionary = ... // add some POST params to authenticate current user


[syncEntity sync];

你可以在这里找到源代码,工作示例和更多说明:github.com/knagode/M3Synchronization

首先,你应该重新考虑你将拥有多少数据、表和关系。在我的解决方案中,我通过Dropbox文件实现了同步。我观察主要MOC的变化,并将这些数据保存到文件(每一行都保存为gzipped json)。如果有互联网连接,我会检查Dropbox上是否有任何更改(Dropbox会给我delta更改),下载它们并合并(最新的胜利),最后放置更改的文件。在同步之前,我把锁文件放在Dropbox上,以防止其他客户端同步不完整的数据。当下载发生变化时,只下载部分数据是安全的(例如失去互联网连接)。当下载完成(全部或部分),它开始加载文件到核心数据。当存在未解决的关系(不是所有文件都下载)时,它会停止加载文件,并尝试稍后完成下载。关系仅存储为GUID,因此我可以轻松地检查加载哪些文件以获得完全的数据完整性。 在对核心数据进行更改之后开始同步。如果没有变化,它会每隔几分钟检查Dropbox上的变化,并在应用程序启动时检查。另外,当更改被发送到服务器时,我会向其他设备发送广播来通知他们更改,这样他们就可以更快地同步。 每个同步实体都有GUID属性(GUID也用作交换文件的文件名)。我也有同步数据库,我存储每个文件的Dropbox修订(我可以比较它时,Dropbox delta重置它的状态)。文件还包含实体名称、状态(已删除/未删除)、guid(与文件名相同)、数据库修订(用于检测数据迁移或避免与从未使用过的应用程序版本同步),当然还有数据(如果行未删除)

这个解决方案适用于数千个文件和大约30个实体。而不是Dropbox,我可以使用键/值存储作为REST web服务,我想稍后做,但没有时间做这个:)目前,在我看来,我的解决方案比iCloud更可靠,这是非常重要的,我可以完全控制它的工作方式(主要是因为它是我自己的代码)。

另一种解决方案是将MOC更改保存为事务-与服务器交换的文件会少得多,但很难按适当的顺序将初始加载到空的核心数据中。iCloud就是这样工作的,其他同步解决方案也有类似的方法,例如TICoreDataSync

< p >—— 更新< / p >

过了一段时间,我迁移到乐团 -我推荐这个解决方案,而不是重新发明轮子。

我认为GUID问题的一个很好的解决方案是“分布式ID系统”。我不确定正确的术语是什么,但我认为这是MS SQL server文档过去所称的(SQL使用/使用这种方法用于分布式/同步数据库)。其实很简单:

所有id由服务器分配。每次同步完成时,首先检查的是“这个客户端上还剩下多少个id ?”如果客户端资源不足,它会向服务器请求一个新的id块。然后,客户端将该范围内的id用于新记录。如果你可以分配一个足够大的块,在下一次同步之前它应该“永远不会”用完,但又不会太大,服务器会随着时间的推移而用完,那么对于大多数需求来说,这是非常有用的。如果客户端已经用完了,处理可以非常简单,只是告诉用户“对不起,您不能添加更多的项目,直到您同步”…如果他们添加了这么多项目,难道他们不应该同步以避免陈旧的数据问题吗?

我认为这优于使用随机guid,因为随机guid不是100%安全的,通常需要比标准ID长得多(128位vs 32位)。您通常根据ID建立索引,并经常将ID号保存在内存中,因此保持它们较小是很重要的。

并不是真的想把它作为答案,但我不知道有人会把它作为评论,我认为这对这个话题很重要,不包括在其他答案中。