iOS NSURLProtocol的具体使用方法详解
本文介绍了iOSNSURLProtocol的具体使用方法详解,分享给大家,具体如下:
NSURLProtocol定义
这两天在优化项目,无意间看到了NSURLProtocol,学习一下顺便总结下来。
NSURLProtocol也是苹果众多黑魔法中的一种,能够让你去重新定义苹果的URL加载系统(URLLoadingSystem)的行为,URLLoadingSystem里有许多类用于处理URL请求,比如NSURL,NSURLRequest,NSURLConnection和NSURLSession等,当URLLoadingSystem使用NSURLRequest去获取资源的时候,它会创建一个NSURLProtocol子类的实例,NSURLProtocol看起来像是一个协议,但其实这是一个类,而且必须使用该类的子类,并且需要被注册。
NSURLProtocol使用范围
只要是使用NSURLConnection或者NSURLSession实现的,你都可以通过NSURLProtocol做一些自定义的操作。
1、自定义请求和响应
2、网络的缓存处理(H5离线包和网络图片缓存)
3、重定向网络请求
4、为测试提供数据Mocking功能,在没有网络的情况下使用本地数据返回。
5、过滤掉一些非法请求
6、快速进行测试环境的切换
7、拦截图片加载请求,转为从本地文件加载
8、可以拦截UIWebView,基于系统的NSURLConnection或者NSURLSession进行封装的网络请求。目前WKWebView无法被NSURLProtocol拦截。
9、当有多个自定义NSURLProtocol注册到系统中的话,会按照他们注册的反向顺序依次调用URL加载流程。当其中有一个NSURLProtocol拦截到请求的话,后续的NSURLProtocol就无法拦截到该请求。
NSURLProtocol自定义
#import@interfaceCustomURLProtocol:NSURLProtocol @end 
要实现下面的方法
+canInitWithRequest: //抽象方法,子类给出是否能相应该请求。如果响应YES,说明自己的CustomURLProtocol实现该请求。 +canonicalRequestForRequest: //抽象方法,重写该方法,可以对请求进行修改,例如添加新的头部信息,修改,修改url等,返回修改后的请求。 +requestIsCacheEquivalent:toRequest: //看都是缓存了 -startLoading: //开始下载,需要在该方法中发起一个请求,对于NSURLConnection来说,就是创建一个NSURLConnection,对于NSURLSession,就是发起一个NSURLSessionTask。一般下载前需要设置该请求正在进行下载,防止多次下载的情况发生 -stopLoading: //停止相应请求,清空请求Connection或Task
使用自定义NSURLProtocol类
1.在单个的UIViewController中使用
//导入自定义NSURLProtocol类 #import"CustomURLProtocol.h" //在ViewDidLoad中添加拦截网络请求的代码 //注册网络请求拦截 [NSURLProtocolregisterClass:[CustomURLProtocolclass]]; //在ViewWillDisappear中添加取消网络拦截的代码 //取消注册网络请求拦截 [NSURLProtocolunregisterClass:[CustomURLProtocolclass]];
2.拦截整个App中所有的网络请求
//直接在AppDelegate中的didFinishLaunchingWithOptions注册网络拦截代码
//注册Protocol
[NSURLProtocolregisterClass:[CustomURLProtocolclass]];
NSURLProtocol使用实例
#defineURLProtocolHandledKey@"URLProtocolHandledKey"
+(BOOL)canInitWithRequest:(NSURLRequest*)request{
//只处理http和https请求
NSString*scheme=[[requestURL]scheme];
if(([schemecaseInsensitiveCompare:@"http"]==NSOrderedSame||
[schemecaseInsensitiveCompare:@"https"]==NSOrderedSame)){
//看看是否已经处理过了,防止无限循环
if([NSURLProtocolpropertyForKey:URLProtocolHandledKeyinRequest:request]){
returnNO;
}
returnYES;
}
returnNO;
}
+(NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request{
/**可以在此处添加头等信息*/
NSMutableURLRequest*mutableReqeust=[requestmutableCopy];
mutableReqeust=[selfredirectHostInRequset:mutableReqeust];
returnmutableReqeust;
}
+(NSMutableURLRequest*)redirectHostInRequset:(NSMutableURLRequest*)request{
if([request.URLhost].length==0){
returnrequest;
}
NSString*originUrlString=[request.URLabsoluteString];
NSString*originHostString=[request.URLhost];
NSRangehostRange=[originUrlStringrangeOfString:originHostString];
if(hostRange.location==NSNotFound){
returnrequest;
}
//定向薄荷喵到主页
NSString*ip=@"bohemiao.com";
//替换域名
NSString*urlString=[originUrlStringstringByReplacingCharactersInRange:hostRangewithString:ip];
NSURL*url=[NSURLURLWithString:urlString];
request.URL=url;
returnrequest;
}
+(BOOL)requestIsCacheEquivalent:(NSURLRequest*)atoRequest:(NSURLRequest*)b{
return[superrequestIsCacheEquivalent:atoRequest:b];
}
-(void)startLoading{
NSMutableURLRequest*mutableReqeust=[[selfrequest]mutableCopy];
//标示该request已经处理过了,防止无限循环
[NSURLProtocolsetProperty:@YESforKey:URLProtocolHandledKeyinRequest:mutableReqeust];
self.connection=[NSURLConnectionconnectionWithRequest:mutableReqeustdelegate:self];
//使用NSURLSession也是一样的
}
-(void)stopLoading{
[self.connectioncancel];
}
-(void)connection:(NSURLConnection*)connectiondidReceiveResponse:(NSURLResponse*)response{
[self.clientURLProtocol:selfdidReceiveResponse:responsecacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
-(void)connection:(NSURLConnection*)connectiondidReceiveData:(NSData*)data{
[self.clientURLProtocol:selfdidLoadData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection*)connection{
[self.clientURLProtocolDidFinishLoading:self];
}
-(void)connection:(NSURLConnection*)connectiondidFailWithError:(NSError*)error{
[self.clientURLProtocol:selfdidFailWithError:error];
}
上面用到的一些NSURLProtocolClient方法
@protocolNSURLProtocolClient//请求重定向 -(void)URLProtocol:(NSURLProtocol*)protocolwasRedirectedToRequest:(NSURLRequest*)requestredirectResponse:(NSURLResponse*)redirectResponse; //响应缓存是否合法 -(void)URLProtocol:(NSURLProtocol*)protocolcachedResponseIsValid:(NSCachedURLResponse*)cachedResponse; //刚接收到Response信息 -(void)URLProtocol:(NSURLProtocol*)protocoldidReceiveResponse:(NSURLResponse*)responsecacheStoragePolicy:(NSURLCacheStoragePolicy)policy; //数据加载成功 -(void)URLProtocol:(NSURLProtocol*)protocoldidLoadData:(NSData*)data; //数据完成加载 -(void)URLProtocolDidFinishLoading:(NSURLProtocol*)protocol; //数据加载失败 -(void)URLProtocol:(NSURLProtocol*)protocoldidFailWithError:(NSError*)error; //为指定的请求启动验证 -(void)URLProtocol:(NSURLProtocol*)protocoldidReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge; //为指定的请求取消验证 -(void)URLProtocol:(NSURLProtocol*)protocoldidCancelAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge; @end 
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
