博客> NSURLProtocol缓存实现步骤
NSURLProtocol缓存实现步骤
2017-11-24 22:45 评论:0 阅读:343 按时吃饭的程序猿
ios 2016 最新 NSURLProtocol 实现流程

一、写一个类继承于NSURLProtocol,并实现以下协议方法:

+ (BOOL)canInitWithRequest:(NSURLRequest *)request:

创建NSURLProtocol实例,NSURLProtocol注册之后,所有的NSURLConnection都会通过这个方法检查是否持有该Http请求。我们可以在这个方法的实现里面进行请求的过滤,筛选出需要进行处理的请求。

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request:

NSURLProtocol抽象类必须要实现。通常情况下这里有一个最低的标准:即输入输出请求满足最基本的协议规范一致。因此这里简单的做法可以直接返回。一般情况下我们是不会去更改这个请求的。如果你想更改,比如给这个request添加一个title,组合成一个新的http请求。

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b:

NSURLProtocol缓存系统设置:如果有两个URL请求,并且他们是相等的,那么这里可以使用相同的缓存空间

- (void)startLoading:

重点利用的一个方法,可以在里面做判断是否使用缓存,如果使用缓存,则对数据进行反归档,并直接实现client几个协议方法;如果不使用缓存,则创建一个NSURLConnection 对象。

  • (void)stopLoading:

当前Connection连接取消的时候被调用。尤其要注意这个StopLoading方法,在本地NSURLRequest初始化的时候,有一个超时时间,在低速网络下,有可能页面还没来得及加载完,这个StopLoading方法就被调用了。 


二、实现NSURLConnection的协议方法

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response:

重点利用的方法,判断是否有对网址进行重定向,若有,在这里实现数据的归档,归档的文件包括response,Data和request。并且调用client的方法:>- (void)URLProtocol:(NSURLProtocol )protocol wasRedirectedToRequest:(NSURLRequest )request redirectResponse:(NSURLResponse *)redirectResponse;

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data:

设置model的Data,并调用client的方法:>- (void)URLProtocol:(NSURLProtocol )protocol didLoadData:(NSData )data;

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error:

清空model,并调用client的方法:>- (void)URLProtocol:(NSURLProtocol )protocol didFailWithError:(NSError )error;

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response:

设置model的response,并调用client的方法:>- (void)URLProtocol:(NSURLProtocol )protocol didReceiveResponse:(NSURLResponse )response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy;

- (void)connectionDidFinishLoading:(NSURLConnection *)connection:

重点利用的方法,归档response,Data,request,并且对model清空数据,并调用client的方法:>- (void)URLProtocolDidFinishLoading:(NSURLProtocol *)protocol; 


三、NSURLProtocol离线缓存的要点:

1、尽早注册你的URLProtocol(application:didFinishLaunchingWithOptions:)。

2、NSURLProtocol是NSURLConnection的handler。NSURLConnection的每个请求都会去便利所有的Protocols,并询问你能处理这个请求么(canInitWithRequest: )。如果这个Protocol返回YES,则第一个返回YES的Protocol会来处理这个connection。Protocols的遍历是反向的,也就是最后注册的Protocol会被优先判断。

3、 当你的handler被选中了,connection就会调用–> initWithRequest:cachedResponse:client:,紧接着会调用–>startLoading。然后你需要负责回调:–>URLProtocol:didReceiveResponse:cacheStoragePolicy:,有些则会调用:–>URLProtocol:didLoadData:, 并且最终会调用–>URLProtocolDidFinishLoading:。你有没有发现这些方法和NSURLConnection delegate的方法非常类似——这绝非偶然!

4、当online的情况下,RNCachingURLProtocol只是负责将请求转发给一个新的NSURLConnection,并且拷贝一份结果给原来的connection。offline时, RNCachingURLProtocol就会从磁盘里载入先前的结果,并将这些数据发回给连接。整个过程只有区区200行代码(不包含Reachability)。

5、这里还有一个有趣的问题,就是当RNCachingURLProtocol创建了一个新的NSURLConnection的,即新的connection也会去找一个handler。 如果RNCachingURLProtocol说可以处理,那么就死循环了。怎么解决呢?通过添加自定义HTTP Header(X-RNCache)来标记这个请求,告诉RNCachingURLProtocol不要再处理这个请求。

6、它可以响应所有的connection,所以你可能需要修改canInitWithRequest:来 选择你要缓存的数据。

收藏
1
sina weixin mail 回到顶部