在我的上一篇文章中,梳理了NSURLSession数据请求的整个流程,关于缓存的处理流程,没有梳理,这篇文章就来探索NSURLCache的系统默认行为.注意!本文只是探索缓存类行为:NSURLRequestUseProtocolCachePolicy的默认行为,IOS系统对于HTTP协议缓存的支持。这种行为是最复杂的行为,理解了这种行为,其它类型就很好理解了。
用法
- 配置缓存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//初始化缓存设置
NSURLCache *chche = [[NSURLCache alloc] initWithMemoryCapacity:1*1024*1024 diskCapacity:20*1024*1024 diskPath:nil];
[NSURLCache setSharedURLCache:chche];
[self initRootController];
return YES;
}
- 配置session
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.timeoutIntervalForRequest = 8.0f;
configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSString *urlString = @"http://static.cnblogs.com/images/icon_addcomment.gif";
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
self.currentRequest = request;
request.HTTPMethod = @"GET";
NSURLSessionDataTask *task = [session dataTaskWithRequest:request]; [task resume];
- 处理NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
NSDictionary *headers = [self.currentRequest allHTTPHeaderFields];
NSLog(@"当前header=%@",headers);
NSLog(@"收到了response%@",response);
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
[CHNetRequestModel shareInstance].request = self.currentRequest;
[CHNetRequestModel shareInstance].headers = res.allHeaderFields;
completionHandler(NSURLSessionResponseAllow);
}
代码解释
首先在应用启动时配置了NSURLCache,配置了20M的磁盘缓存,1M的内存缓存,diskPath表示储存的目录,系统会将缓存信息放在Libary/Caches下,如果diskPath传nil,表示缓存信息储存在Libary/Caches,如果diskPath传@"Request",则缓存信息会放在Library/Caches/Request目录下.
然后配置了NSURLSession,用于网络请求,网络请求的应用,不用过多解释,不了解的可以参考我的另一篇文章 NSURLSession数据请求
最后处理NSURLSessionDelegate的响应,这里只是简单的打印出了HTTP response header
结论
当首次运行时,系统发现本地没有缓存,系统就会向服务端请求数据,此时用charles抓包发现设备向服务端发送了GET请求,服务端返回的状态码为200,当请求完成之后,系统会将缓存信息储存到NSURLCache配置的路径中,第二次请求,系统会查看缓存中是否有数据,如果有数据,系统会查看max-age的值,如果缓存中的max-age的值还没有过期(过期算法是:当前请求的时间,减去服务端上次返回的时间,小于max-age则表示没有过期,大于表示已经过期,该算法只是我的猜测,在测试的时候,发现按照这种逻辑,完全能够解释通), 系统就不会向服务端请求数据(charles抓包也没有发现有数据请求),系统会直接返回200,并将缓存的数据直接换回。如果缓存过期了,系统就会向服务端请求数据,然后刷新缓存中的数据。
需要说明的是,系统默认仅仅是在本地判断max-age的值,如果开发需要支持“If-Modified-Since”字段 则需要自己在request的header中带上。当服务端发现资源没有改变的时候,会返回304状态吗,但是!我们打印response发现,状态吗依然为200!,说明,当服务端发现状态码为304的时候,系统会返回缓存的数据,并将状态嘛修改为200,这个过程对于用户来说是透明的。
以上便是系统对于缓存的默认处理,只有理解了系统的默认行为才能够在项目中灵活运用。
说明!以上是我对系统对缓存的默认行为的梳理,其中缓存的概念和http缓存字段的说明,并没有进行解释,希望大家结合下面的文章来看:
彻底弄懂http缓存机制及原理
NSURLCache