问题 如何将来自Web服务的数据与Core Data同步?


我正在尝试以简单的方式从Web服务同步我的数据。我使用AFNetworking下载数据,并在每个对象上使用唯一标识符,我想插入,删除或更新该数据。

问题是,使用Core Data,您必须在NSObjectManagedContext中实际插入对象以实例化NSManagedObjects。喜欢这个:

MyModel *model = (MyModel *)[NSEntityDescription insertNewObjectForEntityForName:@"MyModel" inManagedObjectContext:moc];
model.value = [jsonDict objectForKey:@"value"];

因此,当我从Web服务获取数据时,我会立即将它们插入Core Data中。因此,没有真正的同步:我只是事先删除所有内容,然后插入从我的Web服务返回的内容。

我想有更好的方法,但我不知道怎么做。有帮助吗?


9894
2018-01-17 20:12


起源

我在这里回答了类似的问题: stackoverflow.com/questions/5035132/...  希望能帮助到你。 - chris
通常情况下,我希望在创建新对象之前尝试查找现有对象,以便我可以更新而不是替换。 - Tom Harrington
你的问题没有简单的答案。将数据从远程服务器与可能长时间离线的移动设备同步实际上是一个“难题”。我敢说 所有 您可以在网络(以及SO)中找到的“简单”解决方案,建议和答案在真实场景中无效 所有 确实有一些明显而且更微妙的问题。在寻找提供“同步”解决方案的第三方服务时,您也应该非常小心。通常,这仅包括一个非常基本的功能集。但也许,这已经足够您的应用程序。 - CouchDeveloper


答案:


您正在遇到经典的插入/更新/删除范例。

答案是,这取决于。如果您获得了一大块json数据,那么您可以使用KVC从该块中提取唯一ID并对您的上下文进行提取以找出已存在的内容。从那里它是一个简单的循环数据块,适当插入和更新。

如果你没有像这样在一个很好的块中获取数据,那么你可能需要对每个记录进行一次获取以确定它是插入还是更新。这要贵得多,应该避免。建议手动批量提取。

删除与获取/更新一样昂贵,因为您需要获取对象以删除它们,因此您也可以正确地处理更新。

更新

是的,有一种从Core Data对象构建字典的有效方法。从Core Data获取现有对象数组后,可以将其转换为字典:

NSArray *array = ...; //Results from Core Data fetch
NSDictionary *objectMap = [NSDictionary dictionaryWithObjects:array forKeys:[array valueForKey:@"identifier"]];

这假定您有一个名为的属性 identifier 在您的核心数据实体中。根据需要更改名称。

使用这一行代码,您现在可以拥有所有现有对象 NSDictionary 然后,当你走JSON时,你可以反对。


12
2018-01-18 03:56



我几乎对我的webservice做了一个批处理请求,并且JSON数组响应中的每个对象都有一个唯一的id。所以我想我可以像你说的那样做循环。但是,有没有一种有效的方法呢?我能看到的最好的方法是循环核心数据结果并构建一个以唯一ID作为索引的映射,然后循环遍历JSON块并根据需要插入/删除/更新。看到更好的方法? - Michael Eilers Smith
@omegatai如果你考虑一下,上面的方法并没有回答什么时候 插, 何时 删除 何时到 更新,哪个对象,以及在不提供同步算法的情况下无法完成,这又需要管理本地和远程的元信息。因此,这种方法只适用于本地数据 只读 并且不允许删除或插入。如果是这种情况,一个简单的方法就是清空本地数据库并插入从服务器接收的所有对象。如果你的对象少于1000个,那么速度也很快。 - CouchDeveloper
如果Web服务返回所有对象而不仅仅是更新的对象,您还可以在所有对象上设置删除标志,执行上述插入和更新,完成后删除所有标记的对象。这样您的数据就可以读写。 - nanako


最简单的方法是将Json恢复到正确映射到它的实体。映射后,确定是否已存在与实体ID匹配的对象,如果是,则获取实体并合并更改。如果没有,请在Core Data中创建一个新实体并将Json还原到它。

我正在建立一个应用程序,我做客户端与Evernote同步。它们在所有对象和服务器级别保留syncUpdate编号。因此,当我开始同步时,检查我的客户端syncUpdate计数是否小于服务器。如果是这样,我知道我不同步。如果我的updateCount是400并且服务器是410,我告诉服务器向我提供updateCount 400和410之间的所有对象。然后我检查是否已经有对象并执行我的更新/创建。

每次在服务器上修改对象时,对象updateCount都会随服务器一起递增。

服务器还保留上次更新的时间戳,我也可以检查。


0
2018-01-21 19:13