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

发布于 2024-07-27 18:38:23 字数 872 浏览 2 评论 0原文

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

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

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

--

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

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

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

I am trying to write a Core Data application for the iPhone that uses an external data source. I'm not really using Core Data to persist my objects but rather for the object life-cycle management. I have a pretty good idea on how to use Core Data for local data, but have run into a few issues with remote data. I'll just use Flickr's API as an example.

The first thing is that if I need say, a list of the recent photos, I need to grab them from an external data source. After I've retrieved the list, it seems like I should iterate and create managed objects for each photo. At this point, I can continue in my code and use the standard Core Data API to set up a fetch request and retrieve a subset of photos about, say, dogs.

But what if I then want to continue and retrieve a list of the user's photos? Since there's a possibility that these two data sets might intersect, do I have to perform a fetch request on the existing data, update what's already there, and then insert the new objects?

--

In the older pattern, I would simply have separate data structures for each of these data sets and access them appropriately. A recentPhotos set and and a usersPhotos set. But since the general pattern of Core Data seems to be to use one managed object context, it seems (I could be wrong) that I have to merge my data with the main pool of data. But that seems like a lot of overhead just to grab a list of photos. Should I create a separate managed object context for the different set? Should Core Data even be used here?

I think that what I find appealing about Core Data is that before (for a web service) I would make a request for certain data and either filter it in the request or filter it in code and produce a list I would use. With Core Data, I can just get list of objects, add them to my pool (updating old objects as necessary), and then query against it. One problem, I can see with this approach, however, is that if objects are externally deleted, I can't know, since I'm keeping my old data.

Am I way off base here? Are there any patterns people follow for dealing with remote data and Core Data? :) I've found a few posts of people saying they've done it, and that it works for them, but little in the way of examples. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

花海 2024-08-03 18:38:23

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

  1. 创建您自己的子类
    NSFetchRequest 需要一个额外的块属性来
    获取完成后执行。
    这是为了你的异步
    向网络请求。 我们打电话吧
    FLRFetchRequest

  2. 创建一个您传递给的类
    这个请求。 我们就这样称呼它吧
    FLRPhotoManagerFLRPhotoManager 有一个方法 executeFetchRequest:,它接受一个
    FLRFetchRequest 的实例和...

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

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

You might try a combination of two things. This strategy will give you an interface where you get the results of a NSFetchRequest twice: Once synchronously, and once again when data has been loaded from the network.

  1. Create your own subclass of
    NSFetchRequest that takes an additional block property to
    execute when the fetch is finished.
    This is for your asynchronous
    request to the network. Let's call
    it FLRFetchRequest

  2. Create a class to which you pass
    this request. Let's call it
    FLRPhotoManager. FLRPhotoManager has a method executeFetchRequest: which takes an
    instance of the FLRFetchRequest and...

    1. Queues your network request based on the fetch request and passes along the retained fetch request to be processed again when the network request is finished.
    2. Executes the fetch request against your CoreData cache and immediately returns the results.
    3. Now when the network request finishes, update your core data cache with the network data, run the fetch request again against the cache, and this time, pull the block from the FLRFetchRequest and pass the results of this fetch request into the block, completing the second phase.

This is the best pattern I have come up with, but like you, I'm interested in other's opinions.

晨光如昨 2024-08-03 18:38:23

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

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

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

It seems to me that your first instincts are right: you should use fetchrequests to update your existing store. The approach I used for an importer was the following: get a list of all the files that are eligible for importing and store it somewhere. I'm assuming here that getting that list is fast and lightweight (just a name and an url or unique id), but that really importing something will take a bit more time and effort and the user may quit the program or want to do something else before all the importing is done.

Then, on a separate background thread (this is not as hard as it sounds thanks to NSRunLoop and NSTimer, google on "Core Data: Efficiently Importing Data"), get the first item of that list, get the object from Flickr or wherever and search for it in the Core Data database (carefully read Apple's Predicate Programming Guide on setting up efficient, cached NSFetchRequests). If the remote object already lives in Core Data, update the information as necessary, if not insert. When that is done, remove the item from the to-be-imported list and move on to the next one.

As for the problem of objects that have been deleted in the remote store, there are two solutions: periodic syncing or lazy, on-demand syncing. Does importing a photo from Flickr mean importing the original thing and all its metadata (I don't know what the policy is regarding ownership etc) or do you just want to import a thumbnail and some info?
If you store everything locally, you could just run a check every few days or weeks to see if everything in your local store is present remotely as well: if not, the user may decide to keep the photo anyway or delete it.
If you only store thumbnails or previews, then you will need to connect to Flickr each time the user wants to see the full picture. If it has been deleted, you can then inform the user and delete it locally as well, or mark it as not being accessible any more.

撕心裂肺的伤痛 2024-08-03 18:38:23

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

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

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

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

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

For a situation like this you could use Cocoa's archiving facilities to save the photo objects (and an index) to disk between sessions, and just overwrite it all every time the app calls home to Flickr.

But since you're already using Core Data, and like the features it provides, why not modify your data model to include a "source" or "callType" attribute? At the moment you're implicitly creating a bunch of objects with source "Flickr API", but you can just as easily treat the different API calls as unique sources and then store that explicitly.

To handle deletion, the simplest way would be to clear the data store each time it's refreshed. Otherwise you'd need to iterate over everything and only delete the photo objects with filenames that weren't included in the new results.

I'm planning to do something similar to this myself so I hope this helps.

PS: If you're not storing the photo objects between sessions at all, you could just use two different contexts and query them separately. As long as they're never saved, and the central store doesn't have anything in it already, it would work just like you describe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文