iOS网络缓存扫盲篇
–使用两行代码就能完成80%的缓存需求
由于微信、QQ、微博、这类的应用使用缓存很“重”,使一般的用户也对缓存也非常习惯。缓存已然成为必备。
缓存的目的的以空间换时间
这句话在动辄就是 300M、600M 的大应用上,得到了很好的诠释。但能有缓存意识的公司,还在少数。
只有你真正感受到痛的时候,你才会考虑使用缓存。
这个痛可能是:
服务器压力、客户端网络优化、用户体验等等。
当我们在谈论缓存的时候,我们在谈论什么?
我们今天将站在小白用户的角度,给缓存这个概念进行重新的定义。
缓存有不同的分类方法:
这里所指的缓存,是一个宽泛的概念。
我们这里主要按照功能进行划分:
– | 第一种 | 第二种 |
---|---|---|
目的 | 优化型缓存 | 功能型缓存 |
具体描述 | 出于优化考虑:服务器压力、用户体验、为用户剩流量等等。同时优化型缓存也有内存缓存和磁盘缓存之分。 | App离线也能查看,出于功能考虑,属于存储范畴 |
常见概念 | GET网络请求缓存、WEB缓存 | 离线存储 |
典型应用 | 微信首页的会话列表、微信头像、朋友圈、网易新闻新闻列表、 | 微信聊天记录、 |
Parse对应的类 | PFCachedQueryController | PFOfflineStore |
重度使用缓存的App: 微信、微博、网易新闻、携程、去哪儿等等。
GET网络请求缓存
概述
首先要知道,POST请求不能被缓存,只有 GET 请求能被缓存。因为从数学的角度来讲,GET 的结果是 幂等 的,就好像字典里的 key 与 value 就是幂等的,而 POST 不 幂等 。缓存的思路就是将查询的参数组成的值作为 key ,对应结果作为value。从这个意义上说,一个文件的资源链接,也叫 GET 请求,下文也会这样看待。
80%的缓存需求:两行代码就可满足
设置缓存只需要三个步骤:
第一个步骤:请使用 GET 请求。
第二个步骤:
如果你已经使用 了 GET 请求,iOS 系统 SDK 已经帮你做好了缓存。你需要的仅仅是设置下内存缓存大小、磁盘缓存大小、以及缓存路径。甚至这两行代码不设置也是可以的,会有一个默认值。代码如下:
NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];
第三个步骤:没有第三步!
你只要设置了这两行代码,基本就可满足80%的缓存需求。AFNetworking 的作者 Mattt曾经说过:
无数开发者尝试自己做一个简陋而脆弱的系统来实现网络缓存的功能,殊不知 NSURLCache 只要两行代码就能搞定且好上 100 倍。
(AFN 是不是在暗讽 SDWebImage 复杂又蹩脚的缓存机制??)
要注意
- iOS 5.0开始,支持磁盘缓存,但仅支持 HTTP
- iOS 6.0开始,支持 HTTPS 缓存
控制缓存的有效性
我们知道:
- 只要是缓存,总会过期。
那么缓存的过期时间如何控制?
上文中的两行代码,已经给出了一个方法,指定超时时间。但这并也许不能满足我们的需求,如果我们对数据的一致性,时效性要求很高,即使1秒钟后数据更改了,客户端也必须展示更改后的数据。这种情况如何处理?
下面我们将对这种需求,进行解决方案的介绍。顺序是这样的:先从文件类型的缓存入手,引入两个概念。然后再谈下,一般数据类型比如 JSON 返回值的缓存处理。
文件缓存:借助ETag或Last-Modified判断文件缓存是否有效
Last-Modified
服务器的文件存贮,大多采用资源变动后就重新生成一个链接的做法。而且如果你的文件存储采用的是第三方的服务,比如七牛、青云等服务,则一定是如此。
这种做法虽然是推荐做法,但同时也不排除不同文件使用同一个链接。那么如果服务端的file更改了,本地已经有了缓存。如何更新缓存?
这种情况下需要借助 ETag 或 Last-Modified 判断图片缓存是否有效。
Last-Modified 顾名思义,是资源最后修改的时间戳,往往与缓存时间进行对比来判断缓存是否过期。
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
总结下来它的结构如下:
如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
判断方法用伪代码表示:
if ETagFromServer != ETagOnClient || LastModifiedFromServer != LastModifiedOnClient
GetFromServer
else
GetFromCache
之所以使用
LastModifiedFromServer != LastModifiedOnClient
而非使用:
LastModifiedFromServer > LastModifiedOnClient
原因是考虑到可能出现类似下面的情况:服务端可能对资源文件,废除其新版,回滚启用旧版本,此时的情况是:
LastModifiedFromServer <= LastModifiedOnClient
但我们依然要更新本地缓存。
Demo10和 Demo11 给出了一个完整的校验步骤:
并给出了 NSURLConnection 和 NSURLSession 两个版本:
/*! @brief 如果本地缓存资源为最新,则使用使用本地缓存。如果服务器已经更新或本地无缓存则从服务器请求资源。 @details 步骤: 1. 请求是可变的,缓存策略要每次都从服务器加载 2. 每次得到响应后,需要记录住 LastModified 3. 下次发送请求的同时,将LastModified一起发送给服务器(由服务器比较内容是否发生变化) @return 图片资源 */
- (void)getData:(GetDataCompletion)completion {
NSURL *url = [NSURL URLWithString:kLastModifiedImageURL];
NSMutableURLRequest *
今天的文章io缓冲_iphone清除app缓存数据分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/69102.html