iOS Network网络篇iOS进阶指南

NSURLCache

2016-02-21  本文已影响715人  tongxyj

原文地址:http://nshipster.com/nsurlcache/
如原作者发现有侵权行为可责令我在24小时之内删除,前提是你能看到。

NSURLCache 在你进行URL请求时为你的应用提供了一套内存和磁盘双重缓存机制。作为Foundation框架的URL Loading System的一部分,NSURLCache会处理所有通过NSURLConncetion(废弃了哇)载入的请求。

网络缓存减少了请求服务器的次数并且提高了在没有网络或者网络状况不好时候的用户体验。

当一个请求从服务器得到响应时,本地将会生成这个响应的一个缓存。下次有同样的请求发起式,本地缓存的响应将立刻返回,NSURLCache自动地返回缓存的响应。

从iOS5开始,应用程序默认有一个全局共享的NSURLCache引用文档

Applications that do not have special caching requirements or constraints should find the default shared cache instance acceptable. An application with more specific needs can create a custom NSURLCache object and set it as the shared cache instance using setSharedURLCache:. The application should do so before any calls to this method.

对于那些有特殊缓存需要的用户来说-可以在iOS平台下的application:didFinishLaunchingWithOptions:方法中或者Mac OS平台下的 –applicationDidFinishLaunching: 方法中对这个全局共享的URLcache进行设置:

- (BOOL)application:(UIApplication *)application 
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ 
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 
                                                     diskCapacity:20 * 1024 * 1024               
                                                         diskPath:nil]; 
[NSURLCache setSharedURLCache:URLCache];
}

对于客户端的请求和服务端的响应来说每一种缓存策略都是有特定用途的。理解这些缓存策略和每种策略之间的关联能够让你为自己的应用程序找到最佳的网络缓存解决方案。

NSURLRequestCachePolicy###

NSURLRequest有一个cachePolicy的属性,它根据下面这些常量来指定客户端请求缓存的方式:

当你看到这些很难理解并经常搞混的枚举时并不会感到惊讶。

让人产生迷惑的其实是 NSURLRequestReloadIgnoringLocalAndRemoteCacheData
NSURLRequestReloadRevalidatingCacheDataaren’t even implemented! (Link to Radar)。

所以这才是你真正要知道的NSURLRequestCachePolicy:

Constant Meaning
UseProtocolCachePolicy 默认的缓存策略
ReloadIgnoringLocalCacheData 忽略本地缓存
ReloadIgnoringLocalAndRemoteCacheData 认真的说,不使用缓存
ReturnCacheDataElseLoad 有缓存就使用,不管其有效性, 无则请求服务端
ReturnCacheDataDontLoad 无网络时使用:总是加载本地缓存,不管其有效性,没有就失败
ReloadRevalidatingCacheData 缓存数据必须得得到服务端确认有效才使用

HTTP Cache Semantics


因为NSURLConnection支持多种协议,包括FTP和HTTP/HTTPS,URL Loading System的API指定的是一套与协议无关的缓存机制,本文中的缓存特指HTTP缓存。

HTTP请求和相应使用头文件传递数据源,包括编码方式,数据的接受类型和缓存指令

Request Cache Headers

NSURLRequest默认会根据当前时间判断是否需要返回一个已经缓存的响应。为了进行更精确的缓存控制,可以设置如下的Request Cache Headers

Response Cache Headers

一个NSHTTPURLResponse 包含了一套 HTTP 头, 通过下列的指令来告诉应用响应如何缓存:

除了Cache-Control之外
, 根据请求头中特定的信息服务器的请求头中会包含与之相关的信息(例如上文中提到的几个字段):

NSURLConnectionDelegate

一旦客户端接收到服务器的响应,NSURLConnection
缓存数据的类。

-connection:willCacheResponse:方法中, cachedResponse对象会从URL connection返回的结果中自动创建。因为没有可变的NSCachedURLResponse版本,想改变任何有关cachedResponse的东西,必须创建一个新的对象,并通过–initWithResponse:data:userInfo:storagePolicy:将改变的值传进去。例如:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{ 
 NSMutableDictionary *mutableUserInfo = [[cachedResponse userInfo] mutableCopy]; 
 NSMutableData *mutableData = [[cachedResponse data] mutableCopy];   
 NSURLCacheStoragePolicy storagePolicy = NSURLCacheStorageAllowedInMemoryOnly; 

 // ...

 return [[NSCachedURLResponse alloc] initWithResponse:[cachedResponse response] 
                                                 data:mutableData 
                                                 userInfo:mutableUserInfo 
                                                 storagePolicy:storagePolicy];
}

如果 -connection:willCacheResponse:方法返回nil,响应不会被缓存。

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{ 
      return nil;
}

当-connection:willCacheResponse:方法没有实现的时候,NSURLConnection将会使用默认的缓存响应,否则会使用这个方法提供的NSCachedURLResponse,所以,除非你想改变或阻止响应缓存操作,不需要实现此代理方法。(上面的方法找了半天在NSURLConnectionDataDelegate这个代理中而不是文中提到的_ NSURLConnectionDelegate_,难道是坑?)

Caveats(忠告)

NSCache
,和NSURLCache并没有什么关系但看起来很相似的同生词, NSURLCache也有很多特性。
iOS 5开始支持磁盘缓存,但是仅仅适用于HTTP,不包括HTTPS请求(不过iOS6起开始支持)。 在Peter Steinberger深入研究了 他的NSURLCache子类的内部实现后,他 在博客写了一篇干货十足的文章

另一篇是Daniel Pasco在Black Pixel发表的描述了在和服务器通信时不设置缓存头发生的一些意想不到的事。


NSURLCache提醒了我们熟悉和系统交流是多么的重要。 当进行iOS和Mac OS开发是, 最主要的部分是 URL Loading System

无数的开发者在用他们网络缓存功能脆弱的系统时都会表现出恼怒和尴尬,因为他们不知道在NSURLCache中写两行代码的效果比用别的方式写100行代码更好。甚至更多的开发人员还不知道网络缓存的好处,而且从去不尝试解决,使他们的应用程序向服务器发出了无数的的不必要的请求。(原来刀哥说的这句话在这里)

改变你看问题的方式,在-application:didFinishLaunchingWithOptions:方法中设置全局共享的NSURLCache来确保你的app构建在一个稳固的基础之上。

上一篇 下一篇

猜你喜欢

热点阅读