当前位置: 移动技术网 > IT编程>移动开发>IOS > iOS NSURLProtocol的具体使用方法详解

iOS NSURLProtocol的具体使用方法详解

2019年07月24日  | 移动技术网IT编程  | 我要评论

中医治肿瘤,监利县吧,78439小游戏娜米

本文介绍了ios nsurlprotocol的具体使用方法详解,分享给大家,具体如下:

nsurlprotocol定义

这两天在优化项目,无意间看到了nsurlprotocol,学习一下顺便总结下来。

nsurlprotocol也是苹果众多黑魔法中的一种,能够让你去重新定义苹果的url加载系统 (url loading system)的行为,url loading system里有许多类用于处理url请求,比如nsurl,nsurlrequest,nsurlconnection和nsurlsession等,当url loading system使用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 <foundation/foundation.h>
 
@interface customurlprotocol : 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中添加拦截网络请求的代码
//注册网络请求拦截
[nsurlprotocol registerclass:[customurlprotocol class]];
//在viewwilldisappear中添加取消网络拦截的代码
//取消注册网络请求拦截
[nsurlprotocol unregisterclass:[customurlprotocol class]];

2.拦截整个app中所有的网络请求

//直接在appdelegate中的didfinishlaunchingwithoptions注册网络拦截代码
//注册protocol
[nsurlprotocol registerclass:[customurlprotocol class]];
nsurlprotocol使用实例

#define urlprotocolhandledkey @"urlprotocolhandledkey"
 
+ (bool)caninitwithrequest:(nsurlrequest *)request{
 //只处理http和https请求
  nsstring *scheme = [[request url] scheme];
  if ( ([scheme caseinsensitivecompare:@"http"] == nsorderedsame ||
   [scheme caseinsensitivecompare:@"https"] == nsorderedsame)){
    //看看是否已经处理过了,防止无限循环
    if ([nsurlprotocol propertyforkey:urlprotocolhandledkey inrequest:request]) {
      return no;
    }
    return yes;
  }
  return no;
}
 
+ (nsurlrequest *) canonicalrequestforrequest:(nsurlrequest *)request {
   /** 可以在此处添加头等信息 */
  nsmutableurlrequest *mutablereqeust = [request mutablecopy];
  mutablereqeust = [self redirecthostinrequset:mutablereqeust];
  return mutablereqeust;
}
 
+(nsmutableurlrequest*)redirecthostinrequset:(nsmutableurlrequest*)request{
  if ([request.url host].length == 0) {
    return request;
  }
 
  nsstring *originurlstring = [request.url absolutestring];
  nsstring *originhoststring = [request.url host];
  nsrange hostrange = [originurlstring rangeofstring:originhoststring];
  if (hostrange.location == nsnotfound) {
    return request;
  }
  //定向薄荷喵到主页
  nsstring *ip = @"bohemiao.com";
 
  // 替换域名
  nsstring *urlstring = [originurlstring stringbyreplacingcharactersinrange:hostrange withstring:ip];
  nsurl *url = [nsurl urlwithstring:urlstring];
  request.url = url;
 
  return request;
}
 
+ (bool)requestiscacheequivalent:(nsurlrequest *)a torequest:(nsurlrequest *)b{
  return [super requestiscacheequivalent:a torequest:b];
}
 
- (void)startloading{
  nsmutableurlrequest *mutablereqeust = [[self request] mutablecopy];
  //标示该request已经处理过了,防止无限循环
  [nsurlprotocol setproperty:@yes forkey:urlprotocolhandledkey inrequest:mutablereqeust];
  self.connection = [nsurlconnection connectionwithrequest:mutablereqeust delegate:self];
  //使用nsurlsession也是一样的
}
 
- (void)stoploading{
  [self.connection cancel];
}
 
- (void) connection:(nsurlconnection *)connection didreceiveresponse:(nsurlresponse *)response {
  [self.client urlprotocol:self didreceiveresponse:response cachestoragepolicy:nsurlcachestoragenotallowed];
}
 
- (void) connection:(nsurlconnection *)connection didreceivedata:(nsdata *)data {
  [self.client urlprotocol:self didloaddata:data];
}
 
- (void) connectiondidfinishloading:(nsurlconnection *)connection {
  [self.client urlprotocoldidfinishloading:self];
}
 
- (void)connection:(nsurlconnection *)connection didfailwitherror:(nserror *)error {
  [self.client urlprotocol:self didfailwitherror:error];
}

上面用到的一些nsurlprotocolclient方法

@protocol nsurlprotocolclient <nsobject>
 
//请求重定向
- (void)urlprotocol:(nsurlprotocol *)protocol wasredirectedtorequest:(nsurlrequest *)request redirectresponse:(nsurlresponse *)redirectresponse;
 
// 响应缓存是否合法
- (void)urlprotocol:(nsurlprotocol *)protocol cachedresponseisvalid:(nscachedurlresponse *)cachedresponse;
 
//刚接收到response信息
- (void)urlprotocol:(nsurlprotocol *)protocol didreceiveresponse:(nsurlresponse *)response cachestoragepolicy:(nsurlcachestoragepolicy)policy;
 
//数据加载成功
- (void)urlprotocol:(nsurlprotocol *)protocol didloaddata:(nsdata *)data;
 
//数据完成加载
- (void)urlprotocoldidfinishloading:(nsurlprotocol *)protocol;
 
//数据加载失败
- (void)urlprotocol:(nsurlprotocol *)protocol didfailwitherror:(nserror *)error;
 
//为指定的请求启动验证
- (void)urlprotocol:(nsurlprotocol *)protocol didreceiveauthenticationchallenge:(nsurlauthenticationchallenge *)challenge;
 
//为指定的请求取消验证
- (void)urlprotocol:(nsurlprotocol *)protocol didcancelauthenticationchallenge:(nsurlauthenticationchallenge *)challenge;
 
@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网