iOS_OC_拦截WKWebview的网络请求

iOS11开始 WebKit支持拦截url  有两种方案可实现

 

1   WKContentRuleListStore规则声明  

1.1 原理   

给WebView提供一个json数据,用来声明规则,告诉webview拦截哪些url,执行怎样的操作,这个json包含两个字段 trigger 和 actio

1.1.1   trigger

trigger字段声明要拦截哪些的url,trigger对应的value也是一个字典,其中url-filter字段是必须的,匹配url的正则表达式,比如匹配所有以gif结尾的url则可以这么写 @"trigger": @{@"url-filter": @".*(.gif)$" }。

1.1.2   action

action字段声明当匹配到对应的url请求时执行哪些操作,其中有个必须的字段 type,表示操作类型  。

block:放弃加载,同时忽略缓存

block-cookies:请求忽略cookie

css-display-none:隐藏关联指定select的css元素,所以当type值设定为css-display-none时,必须同时存在一个字段selector, 什么意思呢,比如网页上有个标签绑定了一个方法  func play(),那就可以在设置type为css-display-none的同时,通过selector:play   来表示 隐藏绑定了play方法的标签

1.2 具体代码  

比如使用json声明不请求所以gif结尾url

#pragma mark - 屏蔽GIF

- (void)shieldGif

{

     NSArray *json = @[@{@"trigger": @{@"url-filter": @".*(.gif)$" },

                         @"action": @{@"type": @"block"}}];

     NSData *jsonData = [NSJSONSerialization dataWithJSONObject:json options:NSJSONWritingPrettyPrinted error:nil];

     NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

 

    [[WKContentRuleListStore defaultStore] compileContentRuleListForIdentifier: @"demoRuleList" encodedContentRuleList:jsonStr completionHandler:^(WKContentRuleList *contentRuleList, NSError *error) {

        if (error) return;

        [self.webView.configuration.userContentController addContentRuleList:contentRuleList];

     }];

}

2   WKWebViewConfiguration Scheme配置

2.1 原理

在创建webview的时候传入一个WKWebViewConfiguration对象,这个对象可以描述哪些scheme的请求要自行处理,当符合这个scheme的请求时会触发代理方法,那么在代理方法中可以自行操作。

2.2 代码实现

比如要监听http、https的请求时可以按以下代码创建webview

WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];

        //支持https和http的方法1  这个需要去hook +[WKwebview handlesURLScheme]的方法,可以去看WKWebView+Custome类的实现

[configuration setURLSchemeHandler:self forURLScheme:@"https"];

 [configuration setURLSchemeHandler:self forURLScheme:@"http"];

_webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];

 

#pragma mark - 网络请求拦截代理方法

- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask{

 

    NSURLRequest *request = urlSchemeTask.request;

    NSURLSession *session = [NSURLSession sharedSession];

 

    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

 

        if ([request.URL.absoluteString.pathExtension isEqualToString:@"gif"]) {

            [urlSchemeTask didReceiveResponse:[NSURLResponse new]];

            [urlSchemeTask didReceiveData:[NSData data]];

        } else {

            [urlSchemeTask didReceiveResponse:response];

            [urlSchemeTask didReceiveData:data];

        }

        [urlSchemeTask didFinish];

    }];

    [task resume];

}

 

- (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {

    [urlSchemeTask didFinish];

}

2.3 会遇到的问题

但是运行起来发现会报一个错

Terminating app due to uncaught exception 'NSInvalidArgumentException' reason: 'http' is a URL scheme that WKWebView handles natively

意思是说WKWebview默认支持http的请求,所以处理这个崩溃的就是让系统认为webview是不支持http和https的请求,具体实现可以使用runtime方法替换,给WKWebview创建一个分类

+ (void)load {

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        Method originalMethod1 = class_getClassMethod(self, @selector(handlesURLScheme:));

        Method swizzledMethod1 = class_getClassMethod(self, @selector(yyhandlesURLScheme:));

        method_exchangeImplementations(originalMethod1, swizzledMethod1);

    });

 

}

+ (BOOL)yyhandlesURLScheme:(NSString *)urlScheme {

    if ([urlScheme isEqualToString:@"http"] || [urlScheme isEqualToString:@"https"]) {

        return NO;  //这里让返回NO,应该是默认不走系统断言或者其他判断啥的

    } else {

        return [self yyhandlesURLScheme:urlScheme];

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值