iOS WKWebView (NSURLProtocol)拦截js、css,图片资源
项目地址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;
}
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];
}
}
下面是代码效果图
项目地址:
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,图片资源的更多相关文章
- iOS WKWebView OC 与 JS 交互学习
我写WKWebView 想让 服务端相应 一个 方法但是不响应,根据 UIWebView 用 JSContext就能拿到响应的处理经验是不是服务端 也需要 对 WKwebView有兼容的一个写法??? ...
- Spring MVC 拦截 js,css,png 等资源
springMVC的<mvc:resources mapping="***" location="***">标签是在spring3.0.4出现的,主 ...
- iOS之在webView中引入本地html,image,js,css文件的方法 - sky//////////////////////////////////////ZZZZZZZZZZZZZZZ
iOS之在webView中引入本地html,image,js,css文件的方法 2014-12-08 20:00:16CSDN-sky_2016-点击数:10292 项目需求 最近开发的项 ...
- iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求
这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...
- iOS进阶之使用 NSURLProtocol 拦截 HTTP 请求(转载)
这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...
- iOS应用内抓包、NSURLProtocol 拦截 APP 内的网络请求
前言 开发中遇到需要获取SDK中的数据,由于无法看到代码,所以只能通过监听所有的网络请求数据,截取相应的返回数据,可以通过NSURLProtocol实现,还可用于与H5的交互 一.NSURLProto ...
- iOS中web与Js的交互
问题 感觉到uni-app框架有pit,公司强推该框架的小哥识趣的闭嘴,考虑到全盘替换周期跟成本挺大,基于uni-app能打包成H5,采用webview+js的原生方式集成 基本结构:原生壳 + we ...
- 配置springMVC之后,引入js,css等资源处理
配置了sringMVC之后,要引入js,css处理: 做法1:在<%page %>下面增加: <%@ taglib prefix="yesurl" uri=&qu ...
- springmvc js/css路径问题
①No mapping found for HTTP request with URI[/msm2/css/login2.css] in DispatcherServlet with name 'sp ...
随机推荐
- JAVA自学笔记08
JAVA自学笔记08 1.构造方法私有,外界就不能再创建对象 2.说明书的制作过程 1)写一个工具类,在同一文件夹下,测试类需要用到工具类,系统将自动编译工具类:工具类的成员方法一般是静态的,因此在测 ...
- django之模版层(template)
上篇主要介绍了django的MTV模型,主要介绍了视图层之路由配置系统url分发和视图层之视图函数view,本篇主要讲解MTV模型中的模版层template. 本篇导论: 模版简介 模版之变量 模版之 ...
- 08、共享变量(Broadcast Variable和Accumulator)
共享变量工作原理 Spark一个非常重要的特性就是共享变量. 默认情况下,如果在一个算子的函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中.此时每个task只能操作自己的那份 ...
- iOS https请求 NSURLSessionDataTask
// // YKSHttpsRequest.m // YKShareSdkDemo // // Created by qingyun on 22/05/2017. // Copyright © ...
- 每天一个linux命令:chown
1.命令简介 chown(Change owner) 用来改变某个文件或目录的所有者和所属的组,该命令可以向某个用户授权,使该用户变成指定文件的所有者或者改变文件所属的组.用户可以是用 ...
- 基于cefsharp的用户浏览器
技术:vc++2015 概述 用于需要制作一个浏览器 winfrom 中浏览器的插件有很多种 如:WebBrowser , Web.kit等 但用于比较稳定 功能齐全的还是cefsharp 详细 ...
- iframe相关小结
父页面调用子页面方法, 子页面加载父页面传送的数据记录了父子间的调用和数据加载. 以下是另一些关于iframe的小结: 1:document.getElementById("ii" ...
- 用反向代理nginx proxy_pass配置解决ie8 ajax请求被拦截问题 ie8用nginx代理实现跨域请求访问 nginx405正向代理request_uri
最近调PC版网站ie8的兼容性,发现所有ajax请求还没到后端服务器就直接ajax error了 ie8发不出ajax请求,断点调试发现ajax全进入了error,提示“No transport” 我 ...
- Effective Java 第三版——69. 仅在发生异常的条件下使用异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- mybatis 中一对多、多对一、多对多、父子继承关系
mybatis 中处理一对多.多对一.多对多.父子继承关系的有关键词:association .collection .discriminator id – 一个 ID 结果:标记出作为 ID 的结果 ...