客户端 (iOS) 上的核心数据缓存来自服务器策略的数据
Posted
技术标签:
【中文标题】客户端 (iOS) 上的核心数据缓存来自服务器策略的数据【英文标题】:Core Data on client (iOS) to cache data from a server Strategy 【发布时间】:2011-06-20 04:46:36 【问题描述】:我编写了许多与后端通信的 ios 应用程序。几乎每次,我都使用 HTTP 缓存来缓存查询并将响应数据 (JSON) 解析为 Objective-C 对象。对于这个新项目,我想知道核心数据方法是否有意义。
这就是我的想法:
iOS 客户端向服务器发出请求,并将对象从 JSON 解析为 CoreData 模型。
每次我需要一个新对象时,我不会直接获取服务器,而是解析 CoreData 以查看我是否已经发出了该请求。如果该对象存在且尚未过期,我将使用获取的对象。
但是,如果对象不存在或已过期(此处将应用一些缓存逻辑),我将从服务器获取对象并相应地更新 CoreData。
我认为拥有这样的架构可以帮助解决以下问题: 1. 避免对后端进行不必要的查询 2. 允许完全支持离线浏览(您仍然可以使用 DataCore 的 RDBMS 进行关系查询)
现在这是我对 SO Gods 的问题:
-
我知道这有点需要对后端逻辑进行第二次编码(服务器 + CoreData),但这是否有点矫枉过正?
我估计有什么限制?
还有其他想法吗?
【问题讨论】:
【参考方案1】:首先,如果您是一名注册的 iOS 开发人员,您应该有权访问 WWDC 2010 Sessions。其中一个会议涵盖了您正在谈论的内容:“第 117 场会议,构建服务器驱动的用户体验”。你应该可以find it on iTunes。
REST / JSON / Core Data 的巧妙组合就像一个魅力,如果你打算重用你的代码可以节省大量时间,但需要有关 HTTP 的知识(如果你想要你的应用程序,还需要有关 Core Data 的知识表现良好且安全)。
所以关键是理解 REST 和 Core Data。
了解REST 意味着了解 HTTP 方法(GET、POST、PUT、DELETE、...HEAD ?)和响应代码(2xx、3xx、4xx、5xx)和标头(Last-Modified、If -Modified-Since, Etag, ...)
了解 Core Data 意味着了解如何设计模型、设置关系、处理耗时的操作(删除、插入、更新),以及如何在后台进行操作以使 UI 保持响应。当然还有如何在 sqlite 上进行本地查询(例如,用于预取 id 以便在获得服务器端等效项后更新对象而不是创建新对象)。
如果您计划为您提到的任务实现可重用的 API,则应确保您了解 REST 和核心数据,因为您可能会在这方面进行最多编码。 (现有的 API - ASIHttpRequest 用于网络层(或任何其他)和任何好的 JSON 库(例如 SBJSON)用于解析都可以完成这项工作。
使这种 API 变得简单的关键是让您的服务器提供 RESTful 服务,并且您的实体拥有所需的属性(dateCreated、dateLastModified 等),以便您可以创建请求(使用 ASIHttpRequest 轻松完成,无论是 GET , PUT, POST, DELETE) 并添加适当的 Http-Headers,例如对于条件 GET:If-Modified-Since。
如果您已经对 Core Data 感到满意并且可以处理 JSON 并且可以轻松地执行 HTTP 请求和处理响应(同样,ASIHttpRequest 在这里有很大帮助,但还有其他的,或者您可以坚持使用较低级别的 Apple NS-类并自己做),那么您只需要为您的请求设置正确的 HTTP 标头,并适当地处理 Http-Response-Codes(假设您的服务器是 REST-ful)。
如果您的主要目标是避免从服务器端等效项重新更新 Core-Data 实体,只需确保您的实体中有“last-modified”属性,并对服务器执行条件 GET (将“If-Modified-Since”Http-Header 设置为您的实体“last-modified”日期。如果该资源未更改(假设服务器为 REST),则服务器将以状态码 304(未修改)响应-ful). 如果它改变了,服务器会将“Last-Modified” Http-Header 设置为最后一次更改的日期,将以 Status-Code 200 响应并在正文中传递资源(例如,以 JSON 格式)。
因此,与往常一样,您的问题的答案可能总是“视情况而定”。 这主要取决于您想在可重用的全能核心数据/休息层中放入什么。
告诉你数字:我花了 6 个月(在我的业余时间,每周 3-10 小时的速度)将我的位置放在我想要的位置,老实说,我仍在重构、重命名、让它处理特殊用例(取消请求、回滚等)并提供细粒度的回调(可达性、网络层、序列化、核心数据保存......),.但它非常干净、精致和优化,希望能满足我雇主的一般需求(具有多个 iOS 应用程序的分类广告在线市场)。那段时间包括学习、测试、优化、调试和不断更改我的 API(首先添加功能,然后改进它,然后从根本上简化它,并再次调试它)。
如果上市时间是您的首要任务,您最好采用简单实用的方法:不要介意可重用性,只需牢记所学,并在下一个项目中重构,在这里和那里重用和修复代码。最后,所有经验的总和可能会在您的 API 如何工作以及它提供什么的清晰愿景中实现。如果您还没有做到这一点,请继续尝试将其纳入项目预算,并尝试尽可能多地重用稳定的 3'rd-Party API。
对于冗长的回复感到抱歉,我觉得您正在涉足构建通用 API 甚至框架之类的事情。这些事情需要时间、知识、管家和长期承诺,而且大多数时候,它们都是浪费时间,因为你永远无法完成它们。
如果您只想处理特定的缓存场景以允许离线使用您的应用并最大限度地减少网络流量,那么您当然可以实现这些功能。只需在您的请求中设置 if-modified-since 标头,检查最后修改的标头或 etag,并将该信息持久保存在您的持久实体中,以便您可以在以后的请求中重新提交此信息。当然,我还建议使用相同的 HTTP 标头在本地缓存(永久)资源,例如图像。
如果您有幸修改(以 REST-ful 方式)服务器端服务,那么只要您实施得当(根据经验,您可以节省多达 3/4 的网络) /parsing code iOS 端,如果服务表现良好(返回适当的 HTTP 状态代码,避免检查 nil,从字符串、日期进行数字转换,提供查找 ID 而不是隐式字符串等...)。
如果您没有这种奢侈,那么该服务至少是 REST-ful(这很有帮助),或者您必须在客户端解决问题(这通常很痛苦)。
【讨论】:
感谢您提及 WWDC 会议,我正在下载它。我已经知道如何处理 Rest-ful 应用程序的流程。我要问的是,进行这样的努力是否太过分了。从您的回答中,我无法判断您是否提倡这种架构,或者您是否支持它,因为您已经使用这种特定架构完成了一个应用程序。你介意澄清一下吗? 一如既往,答案可能是“视情况而定”。 我将编辑我的答案,评论框不允许使用那么多字符 :-) 我会接受您的回答,因为您提供了很多信息,而且确实很有帮助。但是,我决定使用 CoreData,是的,我遇到了一些问题,但现在,它看起来不错。谢谢! 我刚刚搜索了“二进制 plist 性能”,了解到 JSONkit 比二进制 plist 更快。 cocoanetics.com/2011/03/json-versus-plist-the-ultimate-showdown【参考方案2】:有一个我无法尝试的解决方案,因为我的项目太远了,无法重构我的应用程序的服务器缓存方面,但它应该对仍在寻找答案的人们有用:
http://restkit.org/
它与我所做的完全一样,但它比我所做的要抽象得多。那里有非常有见地的东西。我希望它可以帮助别人!
【讨论】:
记录在案:github 上还有另一个新 API:github.com/gowalla/AFNetworking。它不提供 Core Data 持久性(RestKit 提供),但它是一个非常好的基于块的 API,用于与 RESTful 服务交互。它也内置了对 JSON-Parsing 的支持(适用于 iOS 【参考方案3】:我认为这是一种有效的方法。我已经做过很多次了。棘手的部分是当您需要处理同步时:如果客户端和服务器都可以同时更改事物。为此,您几乎总是需要特定于应用的合并逻辑。
【讨论】:
以上是关于客户端 (iOS) 上的核心数据缓存来自服务器策略的数据的主要内容,如果未能解决你的问题,请参考以下文章