项目地址github:<a href="https://github.com/LiuShuoyu/HybirdWKWebVIew/">HybirdWKWebVIew</a>

HybridNSURLProtocol

一个基于WKWebView的hybirde的容器。能拦截所有WKWKWebView的的css,js,png等网络请求的demo
NSURLProtocol 子类,就可以对 app 内所有的网络请求进行:

[NSURLProtocol registerClass:[HybridNSURLProtocol class]]

可是在 WKWebView 中的请求却完全不遵从这一规则,只是象征性+ (BOOL) canInitWithRequest:(NSURLRequest *)request 方法,之后的整个请求流程似乎就与 NSURLProtocol 完全无关了。

使我WKWebView 的一度认为请求不遵守NSURLProtocol协议,所以不走 NSURLProtocol。这个也是很苦扰我的问题。导致我们hybird的容器1.0也是是用UIWebVIew实现的。

但在苹果放在gittub的CustomHTTPProtocol,明显感觉到WKWebview的也是遵守NSURLProtocol,要不也不会走+ (BOOL)canInitWithRequest:(NSURLRequest *)request;后来一个每天看博客和gittub的习惯帮助了我,找到一个大神的不久前开源库。

使用了WKBrowsingContextController和registerSchemeForCustomProtocol。 通过反射的方式拿到了私有的 class/selector。通过kvc取到browsingContextController。通过把注册把 http 和 https 请求交给 NSURLProtocol 处理。

[NSURLProtocol wk_registerScheme:@"http"];
[NSURLProtocol wk_registerScheme:@"https"];

下面直接上源代码吧

//FOUNDATION_STATIC_INLINE 属于属于runtime范畴,你的.m文件需要频繁调用一个函数,可以用static inline来声明。在SDWebImage读取内存的缓存也用到这个声明。
FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
static Class cls;
if (!cls) {
cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
}
return cls;
} FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
} FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
} @implementation NSURLProtocol (WebKitSupport) + (void)wk_registerScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = RegisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
// 放弃编辑器警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
} + (void)wk_unregisterScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = UnregisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
// 放弃编辑器警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}

注册后,客户端所有请求走+ (BOOL)canInitWithRequest:(NSURLRequest *)request。下面是打印的请求的log

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSLog(@"request.URL.absoluteString = %@",request.URL.absoluteString);
NSString *scheme = [[request URL] scheme];
if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
[scheme caseInsensitiveCompare:@"https"] == NSOrderedSame ))
{
//看看是否已经处理过了,防止无限循环
if ([NSURLProtocol propertyForKey:KHybridNSURLProtocolHKey inRequest:request])
return NO;
return YES;
}
return NO;
}

Aaron Swartz

request的重写定向,request的重写定向,替换百度知道的log

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSLog(@"request.URL.absoluteString = %@",request.URL.absoluteString);
NSString *scheme = [[request URL] scheme];
if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
[scheme caseInsensitiveCompare:@"https"] == NSOrderedSame ))
{
//看看是否已经处理过了,防止无限循环
if ([NSURLProtocol propertyForKey:KHybridNSURLProtocolHKey inRequest:request])
return NO;
return YES;
}
return NO;
}

这里最好加上缓存判断,加载本地离线文件, 这个直接简单的例子。

- (void)startLoading
{
NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
//给我们处理过的请求设置一个标识符, 防止无限循环,
[NSURLProtocol setProperty:@YES forKey:KHybridNSURLProtocolHKey inRequest:mutableReqeust]; //这里最好加上缓存判断,加载本地离线文件, 这个直接简单的例子。
if ([mutableReqeust.URL.absoluteString isEqualToString:sourIconUrl])
{
NSData* data = UIImagePNGRepresentation([UIImage imageNamed:@"medlinker"]);
NSURLResponse* response = [[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"image/png" expectedContentLength:data.length textEncodingName:nil];
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];
}
else
{
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
self.task = [session dataTaskWithRequest:self.request];
[self.task resume];
}
}

下面是代码效果图

 
WechatIMG1.png
 
WechatIMG2.jpeg

项目地址:

github:<a href="https://github.com/LiuShuoyu/HybirdWKWebVIew/">HybirdWKWebVIew</a>,对您有帮助,欢迎star。

有问题反馈

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

  • github:<a href="https://github.com/LiuShuoyu/">LiuShuoyu</a>

接受启发的作者的github

github:<a href="https://github.com/yeatse/">Yeatse CC</a>
苹果开发者文档:<a href="https://developer.apple.com/library/content/samplecode/CustomHTTPProtocol/Introduction/Intro.html/">apple</a>

作者:刘小弟
链接:https://www.jianshu.com/p/4fc13d4d5607
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS WKWebView (NSURLProtocol)拦截js、css,图片资源的更多相关文章

  1. iOS WKWebView OC 与 JS 交互学习

    我写WKWebView 想让 服务端相应 一个 方法但是不响应,根据 UIWebView 用 JSContext就能拿到响应的处理经验是不是服务端 也需要 对 WKwebView有兼容的一个写法??? ...

  2. Spring MVC 拦截 js,css,png 等资源

    springMVC的<mvc:resources mapping="***" location="***">标签是在spring3.0.4出现的,主 ...

  3. iOS之在webView中引入本地html,image,js,css文件的方法 - sky//////////////////////////////////////ZZZZZZZZZZZZZZZ

    iOS之在webView中引入本地html,image,js,css文件的方法   2014-12-08 20:00:16CSDN-sky_2016-点击数:10292     项目需求 最近开发的项 ...

  4. iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求

    这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...

  5. iOS进阶之使用 NSURLProtocol 拦截 HTTP 请求(转载)

    这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...

  6. iOS应用内抓包、NSURLProtocol 拦截 APP 内的网络请求

    前言 开发中遇到需要获取SDK中的数据,由于无法看到代码,所以只能通过监听所有的网络请求数据,截取相应的返回数据,可以通过NSURLProtocol实现,还可用于与H5的交互 一.NSURLProto ...

  7. iOS中web与Js的交互

    问题 感觉到uni-app框架有pit,公司强推该框架的小哥识趣的闭嘴,考虑到全盘替换周期跟成本挺大,基于uni-app能打包成H5,采用webview+js的原生方式集成 基本结构:原生壳 + we ...

  8. 配置springMVC之后,引入js,css等资源处理

    配置了sringMVC之后,要引入js,css处理: 做法1:在<%page %>下面增加: <%@ taglib prefix="yesurl" uri=&qu ...

  9. springmvc js/css路径问题

    ①No mapping found for HTTP request with URI[/msm2/css/login2.css] in DispatcherServlet with name 'sp ...

随机推荐

  1. JAVA自学笔记08

    JAVA自学笔记08 1.构造方法私有,外界就不能再创建对象 2.说明书的制作过程 1)写一个工具类,在同一文件夹下,测试类需要用到工具类,系统将自动编译工具类:工具类的成员方法一般是静态的,因此在测 ...

  2. django之模版层(template)

    上篇主要介绍了django的MTV模型,主要介绍了视图层之路由配置系统url分发和视图层之视图函数view,本篇主要讲解MTV模型中的模版层template. 本篇导论: 模版简介 模版之变量 模版之 ...

  3. 08、共享变量(Broadcast Variable和Accumulator)

    共享变量工作原理 Spark一个非常重要的特性就是共享变量.   默认情况下,如果在一个算子的函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中.此时每个task只能操作自己的那份 ...

  4. iOS https请求 NSURLSessionDataTask

    // //  YKSHttpsRequest.m //  YKShareSdkDemo // //  Created by qingyun on 22/05/2017. //  Copyright © ...

  5. 每天一个linux命令:chown

    1.命令简介         chown(Change owner) 用来改变某个文件或目录的所有者和所属的组,该命令可以向某个用户授权,使该用户变成指定文件的所有者或者改变文件所属的组.用户可以是用 ...

  6. 基于cefsharp的用户浏览器

    技术:vc++2015   概述 用于需要制作一个浏览器 winfrom 中浏览器的插件有很多种 如:WebBrowser , Web.kit等 但用于比较稳定 功能齐全的还是cefsharp 详细 ...

  7. iframe相关小结

    父页面调用子页面方法, 子页面加载父页面传送的数据记录了父子间的调用和数据加载. 以下是另一些关于iframe的小结: 1:document.getElementById("ii" ...

  8. 用反向代理nginx proxy_pass配置解决ie8 ajax请求被拦截问题 ie8用nginx代理实现跨域请求访问 nginx405正向代理request_uri

    最近调PC版网站ie8的兼容性,发现所有ajax请求还没到后端服务器就直接ajax error了 ie8发不出ajax请求,断点调试发现ajax全进入了error,提示“No transport” 我 ...

  9. Effective Java 第三版——69. 仅在发生异常的条件下使用异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  10. mybatis 中一对多、多对一、多对多、父子继承关系

    mybatis 中处理一对多.多对一.多对多.父子继承关系的有关键词:association .collection .discriminator id – 一个 ID 结果:标记出作为 ID 的结果 ...