欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS NSURLProtocol的具体使用方法详解

程序员文章站 2023-12-20 10:38:58
本文介绍了ios nsurlprotocol的具体使用方法详解,分享给大家,具体如下: nsurlprotocol定义 这两天在优化项目,无意间看到了nsurlprot...

本文介绍了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

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

上一篇:

下一篇: