8

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

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

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

--

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

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

我在这里离基地很远吗?人们在处理远程数据和核心数据时是否遵循任何模式?:) 我发现一些人说他们已经做到了,并且对他们有用,但几乎没有例子。谢谢。

4

3 回答 3

3

您可以尝试将两件事结合起来。该策略将为您提供一个接口,您可以在其中两次获得 NSFetchRequest 的结果:一次是同步的,另一次是在从网络加载数据时。

  1. 创建您自己的子类, NSFetchRequest它需要一个额外的块属性来在提取完成时执行。这是针对您对网络的异步请求。让我们称之为FLRFetchRequest

  2. 创建一个向其传递此请求的类。让我们称之为 FLRPhotoManagerFLRPhotoManager有一个方法executeFetchRequest:,它采用FLRFetchRequestand...的一个实例

    1. 根据获取请求对您的网络请求进行排队,并在网络请求完成时传递保留的获取请求以再次处理。
    2. 对 CoreData 缓存执行 fetch 请求并立即返回结果。
    3. 现在当网络请求完成时,用网络数据更新你的核心数据缓存,再次对缓存运行 fetch 请求,这一次,从 FLRFetchRequest 中拉取块并将这个 fetch 请求的结果传递到块中,完成第二阶段。

这是我想出的最好的模式,但和你一样,我对别人的意见很感兴趣。

于 2010-09-23T01:50:38.477 回答
2

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

然后,在一个单独的后台线程上(这并不像听起来那么难,这要归功于 NSRunLoop 和 NSTimer,谷歌关于“核心数据:高效导入数据”),获取该列表的第一项,从 Flickr 或任何地方获取对象,然后在 Core Data 数据库中搜索它(仔细阅读 Apple 的 Predicate Programming Guide 关于设置高效、缓存的 NSFetchRequests)。如果远程对象已经存在于 Core Data 中,则根据需要更新信息,如果不插入。完成后,从要导入的列表中删除该项目并移至下一个。

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

于 2009-11-21T13:20:40.017 回答
0

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

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

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

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

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

于 2009-11-10T04:17:31.067 回答