使用Core Data访问远程数据的模式?

时间:2009-07-17 20:25:48

标签: iphone web-services core-data cocoa-design-patterns

我正在尝试为使用外部数据源的iPhone编写核心数据应用程序。我并不是真的使用Core Data来保存我的对象,而是使用对象生命周期管理。我对如何将Core Data用于本地数据有一个很好的想法,但是遇到了一些远程数据问题。我将以Flickr的API为例。

首先,如果我需要说明最近的照片列表,我需要从外部数据源中获取它们。在我检索完列表之后,似乎我应该迭代并为每张照片创建托管对象。此时,我可以继续使用我的代码并使用标准的Core Data API来设置获取请求并检索有关狗的照片子集。

但是如果我想继续并检索用户照片列表怎么办?由于这两个数据集可能相交,我是否必须对现有数据执行获取请求,更新已存在的数据,然后插入新对象?

-

在较旧的模式中,我只是为每个数据集分别拥有单独的数据结构并适当地访问它们。最近的照片集和用户照片集。但由于核心数据的一般模式似乎是使用一个托管对象上下文,似乎(我可能是错的)我必须将我的数据与主数据池合并。但这似乎只是为了获取一系列照片而需要大量开销。我应该为不同的集创建单独的托管对象上下文吗?核心数据是否应该在这里使用?

我认为我对Core Data感兴趣的是之前(对于Web服务)我会请求某些数据并在请求中过滤它或在代码中过滤它并生成我将使用的列表。使用Core Data,我可以获取对象列表,将它们添加到我的池中(根据需要更新旧对象),然后查询它。然而,我可以通过这种方法看到的一个问题是,如果对象被外部删除,我无法知道,因为我保留了旧数据。

我离开基地吗?人们在处理远程数据和核心数据时是否有任何模式? :)我发现有一些人说他们已经完成了它,并且它适用于他们,但很少有例子。感谢。

3 个答案:

答案 0 :(得分:2)

在我看来,你的第一直觉是对的:你应该使用fetchrequests来更新你现有的商店。我用于导入程序的方法如下:获取所有符合导入条件的文件列表并将其存储在某处。我在这里假设获得该列表是快速和轻量级(只是一个名称和一个网址或唯一的ID),但真正导入的东西将需要更多的时间和精力,用户可能会退出该程序或想要做某事在完成所有导入之前的其他操作。

然后,在一个单独的后台线程上(由于NSRunLoop和NSTimer,谷歌在“核心数据:有效导入数据”上),这并不像听起来那么难,获取该列表的第一项,从Flickr获取对象或者在核心数据数据库中搜索并搜索它(仔细阅读Apple的谓词编程指南,了解如何设置高效的缓存NSFetchRequests)。如果远程对象已存在于Core Data中,则根据需要更新信息(如果未插入)。完成后,从待导入列表中删除该项目,然后转到下一个项目。

对于已在远程存储中删除的对象的问题,有两种解决方案:定期同步或延迟按需同步。从Flickr导入照片是否意味着导入原始内容及其所有元数据(我不知道关于所有权的政策是什么等),或者您只是想导入缩略图和一些信息? 如果您在本地存储所有内容,则可以每隔几天或几周运行一次检查,以查看本地商店中的所有内容是否也存在远程:如果没有,用户可能会决定保留照片或删除它。 如果您只存储缩略图或预览,那么每次用户想要查看完整图片时,您都需要连接到Flickr。如果它已被删除,您可以通知用户并在本地删除它,或将其标记为不再可访问。

答案 1 :(得分:2)

您可以尝试两种方式的组合。这个策略将为您提供一个接口,您可以在其中获得两次NSFetchRequest的结果:一次同步,再次从网络加载数据时。

  1. 创建自己的子类 NSFetchRequest需要额外的块属性 在获取完成时执行。 这适用于您的异步 请求到网络。我们打电话吧 它FLRFetchRequest

  2. 创建您传递的课程 这个请求。我们称之为 FLRPhotoManagerFLRPhotoManager有一个方法executeFetchRequest:,它需要一个 FLRFetchRequest的实例和......

    1. 根据获取请求对您的网络请求进行排队,并在网络请求完成时传递保留的获取请求再次
    2. 对CoreData缓存执行抓取请求并立即返回结果。
    3. 现在,当网络请求完成时,使用网络数据更新核心数据缓存,再次针对缓存运行获取请求,这次,从FLRFetchRequest中提取块并将此获取请求的结果传递给块,完成第二阶段。
  3. 这是我提出的最佳模式,但与您一样,我对其他人的意见感兴趣。

答案 2 :(得分:0)

对于这种情况,您可以使用Cocoa的归档工具在会话之间将照片对象(和索引)保存到磁盘,并且每次应用程序调用Flickr的主页时都会覆盖它。

但是既然您已经在使用Core Data,并且喜欢它提供的功能,为什么不修改您的数据模型以包含“source”或“callType”属性?目前,您隐式使用源“Flickr API”创建了一堆对象,但您可以轻松地将不同的API调用视为唯一源,然后将其显式存储。

要处理删除,最简单的方法是每次刷新时清除数据存储。否则,您需要迭代所有内容,只删除具有未包含在新结果中的文件名的照片对象。

我打算自己做类似的事情,所以我希望这会有所帮助。

PS:如果你根本没有在会话之间存储照片对象,你可以使用两个不同的上下文并分别查询它们。只要它们从未被保存过,并且中央商店已经没有任何内容,它就会像你描述的一样工作。