监听本地URL请求(NSURLProtocol)

NSURLProtocol 是IOS中非常重要的一个部分,IOS中我们经常使用的网络请求NSURLConnection以及WebView的页面加载都会被NSURLProtocol截获,因此这个部分的核心就是如何来用这个部分:

下面我将根据使用的步骤来描述NSURLProtocol的使用过程:

(1)首先我们需要创建一个类,继承NSURLProtocol并且实现代理继承:

@interfaceMyURLProtocol () <NSURLConnectionDelegate>

@end

(2)在需要使用的地方,注册这个协议一般情况下,这个协议在AppDelegate文件中注册:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [NSURLProtocol  registerClass:[MyURLProtocolclass]];
    // Override point for customization after application launch.
    returnYES;
}
下面就可以使用这个东东了

可以正常的使用这个NSURLProtocol只需要简单的使用下面9个方法,这九个方法是这个协议可以实现的最基本和最重要的几个方法,当然它还有很多高级的功能,这里就不一一介绍了。

最重要的9个方法如下:

<1>

 @method:创建NSURLProtocol实例,NSURLProtocol注册之后,所有的NSURLConnection都会通过这个方法检查是否持有该Http请求。

 @parma :

 @return: YES:持有该Http请求NO:不持有该Http请求

+ (BOOL)canInitWithRequest:(NSURLRequest *)request

#pragma mark --NSURLProtocol Hold RelevantMethod 4个方法

<2-5>

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

 @parma :本地HttpRequest请求:request

 @return:直接转发

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

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

 @parma :本地HttpRequest请求:request

 @return:

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

 @method:获取网站上的数据建立connect连接

 @parma :

 @return:

- (void)startLoading

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

 @parma :

 @return:

- (void)stopLoading

<6-9>接收数据

#pragma mark --NSURLProtocol Delegate 4个方法

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

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

- (void)connectionDidFinishLoading:(NSURLConnection*)connection

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

注意这里的方法中:

canInitWithRequest 会创建一个实例,YES时候,然后继续调用startLoading。这里会继续调用canInitWithRequest。陷入死循环,因此这里我们常用的做法是设置一个[NSURLProtocolsetProperty:@YESforKey:@"MyURLProtocolHandledKey"inRequest:newRequest];

这样就可以避免程序陷入死循环。

下面给出一段参考代码:

@implementation MyURLProtocol
/**
 @method: 创建NSURLProtocol实例,NSURLProtocol注册之后,所有的NSURLConnection都会通过这个方法检查是否持有该Http请求。
 @parma :
 @return: YES:持有该Http请求 NO:不持有该Http请求
 */
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
   staticNSUInteger requestCount =0;
   NSLog(@"Request #%u: URL = %@", requestCount++, request);
    if([NSURLProtocolpropertyForKey:@"MyURLProtocolHandledKey"inRequest:request]) {
       returnNO;
    }
    returnYES;
}
#pragma mark --NSURLProtocol Hold Relevant Method
/**
 @method: NSURLProtocol抽象类必须要实现。通常情况下这里有一个最低的标准:即输入输出请求满足最基本的协议规范一致。因此这里简单的做法可以直接返回。一般情况下我们是不会去更改这个请求的。如果你想更改,比如给这个request添加一个title,组合成一个新的http请求。
 @parma : 本地HttpRequest请求:request
 @return: 直接转发
 */
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest*)request {
   return request;
}
/**
 @method: NSURLProtocol缓存系统设置:如果有两个URL请求,并且他们是相等的,那么这里可以使用相同的缓存空间
 @parma : 本地HttpRequest请求:request
 @return:
 */
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
    return [superrequestIsCacheEquivalent:atoRequest:b];
}

- (void)startLoading {
   NSMutableURLRequest *newRequest = [self.requestmutableCopy];
            [NSURLProtocolsetProperty:@YESforKey:@"MyURLProtocolHandledKey"inRequest:newRequest];
    
    self.connection = [NSURLConnectionconnectionWithRequest:newRequestdelegate:self];
}
/**
 @method: 当前Connection连接取消的时候被调用
 @parma :
 @return:
 */
- (void)stopLoading {
    [self.connectioncancel];
    self.connection =nil;
}
#pragma mark --NSURLProtocol Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.clientURLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.clientURLProtocol:selfdidLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.clientURLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.clientURLProtocol:selfdidFailWithError:error];
}
@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lin&Yi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值