[转]用NSURLPROTOCOL实现代理和缓存
2013-05-06 10:42 waddell 阅读(2866) 评论(0) 编辑 收藏 举报原理
NSURLProtocol可以用来劫持全局的由NSURLConnection发起的网络请求,通过覆写方法,你可以获知NSURLConnection需要发起的NSURLRequest,你可以自行发起网络请求,并且把数据丢过请求的发起者。通过这种方法,一般来说,你可以实现代理和缓存等功能。 由于UIWebView也是走的这套协议,所以你甚至可以自己开发一个走代理的浏览器。
方法
注册自定义协议
[NSURLProtocol registerClass:[HSUProxyURLProtocol class]];
实现自定义协议
Header文件
#import <Foundation/Foundation.h> @interface HSUProxyURLProtocol : NSURLProtocol @end
Implementation文件
#import "HSUProxyURLProtocol.h" @implementation HSUProxyURLProtocol { #可以在此定义数据容器,连接等 } - (void)startLoading { #可以这样子拿到原来的请求,用以拼装自己的请求 NSMutableURLRequest *proxyRequest = [self.request mutableCopy]; } - (void)stopLoading { #请求在这里该结束了,在此终止自己的请求吧 [connection cancel]; } #这几个不是Protocol的方法,是自发起的URLConnection的回调 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { #此方法会收到一部分或者全部的数据,可以这样子丢给原始请求的发起者 [self.client URLProtocol:self didLoadData:sourceData]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { #和上一个方法类似,这里作为错误通知 [self.client URLProtocol:self didFailWithError:error]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { #这里是收到响应的头部信息,比如HTTP Header,可视情况做对self.client做相应操作,也可以不做处理 } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { #自己的请求加载完成了,这样子可以通知self.client [self.client URLProtocolDidFinishLoading:self]; } + (BOOL)canInitWithRequest:(NSURLRequest *)request { #根据request来决定要不要劫持 #需要特别注意的是,如果你用NSURLConnection来发起代理请求,那么那个代理请求的request也同样会经过这里来做判决,所以一定要判断是不是代理请求,然后返回NO } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { #这里是干嘛的,我还没研究清楚,就简单的返回了原始值,有兴趣的话你可以研究一下 return request; } @end
以上我已经基本描述了每个方法是做什么的,怎么用的。 最后可以参考一下我在开源项目中的实现 Tweet4China2 另参见一个别人写的缓存 RNCachingURLProtocol