1.前言
本文主要介绍NSURLCache的相关内容,NSCache的相关介绍见上篇
2.简介
The NSURLCache class implements the caching of responses to URL load requests by mapping NSURLRequest objects to NSCachedURLResponse objects. It provides a composite in-memory and on-disk cache, and lets you manipulate the sizes of both the in-memory and on-disk portions. You can also control the path where cache data is stored persistently.
NSURLCache 用于进行请求数据的缓存,提供磁盘+内存缓存。 response是通过请求的url+参数来作为key储存的
3.缓存策略
当使用 NSURLSession 时 , 我们可以直接通过 NSMutableURLRequest 来指定 NSURLRequestCachePolicy .
官方API:
+(instancetype)requestWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval;
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy) {
NSURLRequestUseProtocolCachePolicy = 0, //默认策略
NSURLRequestReloadIgnoringLocalCacheData = 1, //忽略缓存,必须从远程地址下载;
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented 未实现
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
NSURLRequestReturnCacheDataElseLoad = 2, // 无论缓存是否过期 , 有就使用缓存 , 没有就请求数据.
NSURLRequestReturnCacheDataDontLoad = 3,// 无论缓存是否过期 , 有就使用缓存 , 没有就请求失败.
NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented 未实现 }
- (void)example_1{
NSURL *url = [NSURL URLWithString:@"http://via.placeholder.com/50x50.jpg"];
//默认使用 HTTP缓存策略来进行缓存
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"error warning : %@",error);
}else{
//从缓存当中读取数据!
NSData *tempData = data;
NSString *responseStr = [[NSString alloc] initWithData:tempData encoding:NSUTF8StringEncoding];
NSLog(@"response:%@",response);
}
}] resume];
}
上面所谓的默认策略即遵循 HTTP Header 中的缓存策略:在 HTTP 中,控制缓存开关的字段有两个:Pragma 和 Cache-Control . Pragma 是旧产物,已经逐步抛弃,有些网站为了向下兼容还保留了这两个字段. 在请求中使用 Cache-Control 时,它可选的值有:
3.1 缓存校验
在缓存中,我们需要一个机制来验证缓存是否有效。比如服务器的资源更新了,客户端需要及时刷新缓存;又或者客户端的资源过了有效期,但服务器上的资源还是旧的,此时并不需要重新发送。缓存校验就是用来解决这些问题的。服务端返回的response 会带有两个字段 Last-Modified 和 etag
- Last-Modified :服务端在返回资源时,会将该资源的最后更改时间通过 Last-Modified 字段返回给客户端。
- 客户端下次请求时通过 If-Modified-Since 或者 If-Unmodified-Since 带上 Last-Modified ,服务端检查该时间是否与服务器的最后修改时间一致:
- 如果一致,则返回 304 状态码,不返回资源;
- 如果不一致则返回 200 和修改后的资源,并带上新的时间。
- If-Modified-Since 和 If-Unmodified-Since 的区别是:
- If-Modified-Since:告诉服务器如果时间一致,返回状态码 304
- If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码 412
- 客户端下次请求时通过 If-Modified-Since 或者 If-Unmodified-Since 带上 Last-Modified ,服务端检查该时间是否与服务器的最后修改时间一致:
- etag:单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用 Etag 来处理。服务器通过某个算法对资源进行计算,取得一串值(类似于文件的 hash 值),之后将该值通过 Etag 返回给客户端。
- 客户端下次请求时通过 If-None-Match 或 If-Match 带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。
3.2 浏览器加载HTTP缓存机制流程
从整个流程来看 , 他们如下图:
3.3 HTTP 缓存内容查看
打开沙盒路径下的Library/Caches 中,你可以看到缓存文件: 本次 HTTP 请求信息、Response信息都在各个表中存储完毕.
3.4 平时我们应用
默认就已经设置好了512kb的内存缓存空间,以及10MB的磁盘缓存空间。可能你的代码中并没有写任何与NSURLCache有关的东西,但其实它已经默默的开始帮你进行缓存了。
print(NSURLCache.sharedURLCache().diskCapacity)
//output:
//10000000
print(NSURLCache.sharedURLCache().memoryCapacity)
//output:
//512000
使用NSURLCache之前需要在AppDelegate中缓存空间的设置:
我们也可自己进行设置缓存的大小
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
diskCapacity:20 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:URLCache]; }
遵守默认设置或者自定义设置之后,我们通过NSURLSession 发送请求时,可以使用使用NSMutableURLRequest 默认的缓存策略,也可以使用其他的缓存策略
4. 缓存原理
NSURLCache 默认进行了内存+磁盘缓存,但是具体如何进行内存和磁盘缓存的相关介绍比较少,需要阅读源码,后期阅读源码就补充本节内容。但是猜测如下:
- 内存缓存 :NSCache
- 磁盘缓存:数据库+文件
5. 参考
https://juejin.im/post/5d76162bf265da03b120738d#heading-12 https://www.jianshu.com/p/aa49bb3555f4