iOS - 让WKWebView 支持 NSURLProtocol
iOS8以后,苹果推出了新框架Webkit,提供了替换UIWebView的组件WKWebView。各种UIWebView的问题没有了,速度更快了,占用内存少了,一句话,WKWebView是App内部加载网页的最佳选择!我们做开发最关系的是内存问题,基本上网上所有的资料都在说WKWebview的内存占用会更少,但是到底少了多少我这边做了下测试,同样是加载163的首页
从上图看出内存大概能优化百分之八十左右,而且从网页的滑动上也确实有所改善。这么明显的性能提升但是苹果并没有完全放弃UIWebView也一定有他的道理,就拿本文要讲的NSURLProtocol拦截请求来说,WKWebview的兼容并不UIWebView好,还需要开发者做一些操作。
WebKit源码分析
由于WKWebview是基于webkit内核来做的,所以我们在使用的时候需要导入一个这样的东西。
#import <WebKit/WebKit.h>
通过这个我们可以猜到WKWebview中所有的请求以及一些逻辑肯定走的都是webkit里面的东西,所以他对于网页的加载之之类的操作也不会走系统本省的URL Loading System,这么说来他的请求不能被NSURLProtocol拦截也是理所当然的了。不过WKWebview是否真的和NSURLProtocol一点关系都没有还需要去研究,幸好webkit是开源的,github上很容易找到源码(大小大概是1G多点的zip,花了我将近一天时间来看)。拉下代码直接搜索NSURLProtocol,看看有没有有关的信息
看来的确是有和NSURLProtocol有关系,后面通过断点的调用栈中也找到了
+ [NSURLProtocol canInitWithRequest:]
这样的字样,再通过网上查一些资料也证实了我的猜想,其实WKWebview在一开始时候是会调用到NSURLProtocol中的入口方法canInitWithRequest的,但是就没有然后了,也就是说WKWebview是和NSURLProtocol有一定关联,只是在NSURLProtocol的入口处返回NO所以导致NSURLProtocol不接管WKWebview的请求。我们点进webkit源码中的CustomProtocol可以看到,整体的结构我们都差不多,但是我注意到每个CustomProtocol的入口函数都有这样一个判断:
(粉色的可以暂时认定为是它内部的一个custom字符串)通过这个可以猜想,WKWebview并不是不走NSURLProtocol,而是需要满足他的一个规则,他才会在入口函数这里返回YES来给你放行,这个规则便是你所请求的URL的Scheme要和它内部配置的CustomScheme相同。不过这里有一个疑问,苹果在使用webkit时候为什么会把http/https这样大众化的scheme过滤掉,看来他是不建议开发者来使用NSURLProtocol。接下来我们来看这个CustomScheme,既然苹果内部规定好的那么一定能通过某种方式来注册一个自己的scheme,实在不行就hook嘛。通过翻他的源码发现最终都指向一句代码
[WKBrowsingContextController registerSchemeForCustomProtocol:testScheme];
方法实现为
+ (void)registerSchemeForCustomProtocol:(NSString *)scheme
{
WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(scheme);
} void WebProcessPool::registerGlobalURLSchemeAsHavingCustomProtocolHandlers(const String& urlScheme)
{
if (!urlScheme)
return; globalURLSchemesWithCustomProtocolHandlers().add(urlScheme);
for (auto* processPool : allProcessPools())
processPool->registerSchemeForCustomProtocol(urlScheme);
}
通过方法名字可以看出这个就是那个向webkit注册CustomScheme的方法,只要我们在注册完我们自己的CustomProtocol之后在调用该方法应该就可以了。通过他的源码也进一步印证了我的猜想(他也是这么写的)
具体实施
找到了方法就要去实施,不过因为registerSchemeForCustomProtocol是WKBrowsingContextController的类方法,所以只能用WKBrowsingContextController去调用,但是在webkit的头文件发现WKBrowsingContextController并没有开放出来,所以我们采用NSClassFromString和NSSelectorFromString方法来拿到类和对应的方法,整体代码如下
//注册自己的protocol
[NSURLProtocol registerClass:[CustomProtocol class]]; //创建WKWebview
WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc] init];
WKWebView * wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(, , [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) configuration:config];
[wkWebView loadRequest:webViewReq];
[self.view addSubview:wkWebView]; //注册scheme
Class cls = NSClassFromString(@"WKBrowsingContextController");
SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
if ([cls respondsToSelector:sel]) {
// 通过http和https的请求,同理可通过其他的Scheme 但是要满足ULR Loading System
[cls performSelector:sel withObject:@"http"];
[cls performSelector:sel withObject:@"https"];
}
值得注意
- 关于私有API
因为WKBrowsingContextController和registerSchemeForCustomProtocol应该是私有的所以使用时候需要对字符串做下处理,用加密的方式或者其他就可以了,实测可以过审核的。
第三方的库
iOS - 让WKWebView 支持 NSURLProtocol的更多相关文章
- iOS App 不支持http协议 App Transport Security has blocked a cleartext HTTP (http://)
目前iOS已经不支持http协议了,不过可以通过info.plist设置允许 App Transport Security has blocked a cleartext HTTP (http://) ...
- [其它]iOS 12.2支持电信VoLTE了,中国电信教你如何开通:只要三步
iOS 12.2支持电信VoLTE了,中国电信教你如何开通:只要三步 link :https://baijiahao.baidu.com/s?id=1629039609897267682&wf ...
- 微信小程序中涉及虚拟产品购买,ios暂不支持的相关整理意见
这个东西呢也不能怪微信小程序,属实苹果搞的事情,那怎么小程序相关内容去通过审核呢? 首先我们要搞清楚哪些属于虚拟商品:如某某书币,某某会员,或者是提前编辑好的网课,文档等都属虚拟商品购买,简言之就是没 ...
- iOS 8 WKWebView
首先看看这篇文章,写得很好:http://nshipster.cn/wkwebkit/ 再推荐去看看 iOS_8_by_Tutorials 这本书里的 WKWebView相关章节! 我这里说下自己的简 ...
- iOS H5容器的一些探究(二):iOS 下的黑魔法 NSURLProtocol
来源:景铭巴巴 链接:http://www.jianshu.com/p/03ddcfe5ebd7 iOS H5 容器的一些探究(一):UIWebView 和 WKWebView 的比较和选择 一.前言 ...
- iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求
这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...
- iOS进阶之使用 NSURLProtocol 拦截 HTTP 请求(转载)
这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...
- iOS 8 WKWebView 知识点
首先看看这篇文章,写得很好:http://nshipster.cn/wkwebkit/ 再推荐去看看 iOS_8_by_Tutorials 这本书里的 WKWebView相关章节! 我这里说下自己的简 ...
- Unity3d使用高通Vuforia发布IOS工程不支持64位的一些解决办法
1.将Unit升级至4.6.x或5.0.x,将Vuforia差距升级到最新版本(vuforia-unity-mobile-android-ios-4-0-105 ) 2.平台Other Setting ...
随机推荐
- 怎样使用ZOL一键安装器下载中关村在线的源安装包
怎样使用ZOL一键安装器下载中关村在线的源安装包 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 摘要 中关村在线近期開始推出ZOL一键安装器,用户直 ...
- Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题
主要用到协程(Coroutines)和游戏对象的生命周期(GameObject Lifecycle)基础知识,巧妙解决了游戏重启的问题. 关于协程,这里有篇文章我觉得写的非常好,理解起来也很容易.推荐 ...
- AVL树平衡旋转详解
AVL树平衡旋转详解 概述 AVL树又叫做平衡二叉树.前言部分我也有说到,AVL树的前提是二叉排序树(BST或叫做二叉查找树).由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, ...
- Spring AOP获取拦截方法的参数名称跟参数值
注意:这种方式需要JDK1.8版本支持 开始:http://www.cnblogs.com/wing7319/p/9592184.html 1.aop配置: <aop:aspectj-autop ...
- hyper-v的p2v工具
1.Disk2vhd v1.64 可以在线p2v http://technet.microsoft.com/en-us/sysinternals/ee656415.aspx 2.物理机转换到HYPER ...
- java中常用jar包
commons-io.jar:可以看成是java.io的扩展,用来帮助进行IO功能开发.它包含三个主要的领域:Utilityclasses-提供一些静态方法来完成公共任务.Filters-提供文件过滤 ...
- 转发:查看centos中的用户和用户组
1.用户列表文件:/etc/passwd/ 2.用户组列表文件:/etc/group 3.查看系统中有哪些用户: cut -d : -f 1 /etc/passwd 4.查看可以登录系统的用户: ca ...
- SCWS 中文分词_测试成功
地址: http://www.xunsearch.com/scws/index.php
- JavaScript中的namespace
<head> <title> New Document </title> <script> var global = window.global||{} ...
- Jmeter进行接口测试
原文地址:https://www.cnblogs.com/nancyzhu/p/8035042.html web接口测试工具: 手工测试的话可以用postman ,自动化测试多是用到 Jmeter(开 ...