iOS8以后,苹果推出了新框架Webkit,提供了替换UIWebView的组件WKWebView。各种UIWebView的问题没有了,速度更快了,占用内存少了,一句话,WKWebView是App内部加载网页的最佳选择!我们做开发最关系的是内存问题,基本上网上所有的资料都在说WKWebview的内存占用会更少,但是到底少了多少我这边做了下测试,同样是加载163的首页

 
使用UIWebView的内存
 
 
使用WKWebview的内存

从上图看出内存大概能优化百分之八十左右,而且从网页的滑动上也确实有所改善。这么明显的性能提升但是苹果并没有完全放弃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的入口函数都有这样一个判断:

 
入口函数1
 
入口函数2

(粉色的可以暂时认定为是它内部的一个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之后在调用该方法应该就可以了。通过他的源码也进一步印证了我的猜想(他也是这么写的)

 
webkit源码
具体实施

找到了方法就要去实施,不过因为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应该是私有的所以使用时候需要对字符串做下处理,用加密的方式或者其他就可以了,实测可以过审核的。

第三方的库

GitHub:NSURLProtocol-WebKitSupport

iOS - 让WKWebView 支持 NSURLProtocol的更多相关文章

  1. 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://) ...

  2. [其它]iOS 12.2支持电信VoLTE了,中国电信教你如何开通:只要三步

    iOS 12.2支持电信VoLTE了,中国电信教你如何开通:只要三步 link :https://baijiahao.baidu.com/s?id=1629039609897267682&wf ...

  3. 微信小程序中涉及虚拟产品购买,ios暂不支持的相关整理意见

    这个东西呢也不能怪微信小程序,属实苹果搞的事情,那怎么小程序相关内容去通过审核呢? 首先我们要搞清楚哪些属于虚拟商品:如某某书币,某某会员,或者是提前编辑好的网课,文档等都属虚拟商品购买,简言之就是没 ...

  4. iOS 8 WKWebView

    首先看看这篇文章,写得很好:http://nshipster.cn/wkwebkit/ 再推荐去看看 iOS_8_by_Tutorials 这本书里的 WKWebView相关章节! 我这里说下自己的简 ...

  5. iOS H5容器的一些探究(二):iOS 下的黑魔法 NSURLProtocol

    来源:景铭巴巴 链接:http://www.jianshu.com/p/03ddcfe5ebd7 iOS H5 容器的一些探究(一):UIWebView 和 WKWebView 的比较和选择 一.前言 ...

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

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

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

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

  8. iOS 8 WKWebView 知识点

    首先看看这篇文章,写得很好:http://nshipster.cn/wkwebkit/ 再推荐去看看 iOS_8_by_Tutorials 这本书里的 WKWebView相关章节! 我这里说下自己的简 ...

  9. Unity3d使用高通Vuforia发布IOS工程不支持64位的一些解决办法

    1.将Unit升级至4.6.x或5.0.x,将Vuforia差距升级到最新版本(vuforia-unity-mobile-android-ios-4-0-105 ) 2.平台Other Setting ...

随机推荐

  1. Revit API PickPoint过滤条件

    //过滤选择,加上过滤条件,没有看出来差别. [TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)] publ ...

  2. C#中使用 SendMessage 向非顶端窗体发送组合键

    开门见山,不废话了, 直接举例说明一下: 比如发送ALT + F 以下是 用spy++截取的消息内容 <00001> 000310DC P WM_SYSKEYDOWN nVirtKey:V ...

  3. SpringMVC核心分发器DispatcherServlet分析

    本文将分析SpringMVC的核心分发器DispatcherServlet的初始化过程以及处理请求的过程,让读者了解这个入口Servlet的作用. DispatcherServlet初始化过程 在分析 ...

  4. 转载-vim配置收藏

    转载自:http://www.cnblogs.com/ma6174/archive/2011/12/10/2283393.html 1.按F5可以直接编译并执行C.C++.java代码以及执行shel ...

  5. 回顾2018年最受欢迎的十四款NoSQL产品

    ​​虽然NoSQL的流行与火起来才短短一年的时间,但是不可否认,现在已经开始了第二代运动.尽管早期的堆栈代码只能算是一种实验,然而现在的系统已经更加的成熟.稳定.不过现在也面临着一个严酷的事实:技术越 ...

  6. TerminateProcess的使用问题

    最好时外部进程来结束目标进程,类似于任务管理器的结束目标进程方式.如果是自身进程想结束自身,可能不同版本的windows行为不一致,有一些能自身强制退出,有一些强制退出不了. 本来MSDN上就说了这个 ...

  7. 【tp5】tp5实现空模块、空控制器、空操作的页面404跳转

    写在最开始:本教程适用于tp5路由的[强制模式+半pathinfo模式+pathinfo模式],通用. 比网上的[通过路由去控制空模块更强力.更全面]. PS:路由控制空模块缺点:仅仅在[强制模式下才 ...

  8. 使用 bibtex4word 实现在 office word 中管理并插入参考文献

    使用 bibtex4word 实现在 office word 中管理并插入参考文献, 简单的步骤流程如下: 1. 下载bibtex4word.zip  (无需安装): 下载地址: http://www ...

  9. 基于Centos搭建 Firekylin 个人网站

    系统要求: CentOS 7.2 64 位操作系统 安装 Node.js 使用 yum 命令安装 Node.js curl --silent --location https://rpm.nodeso ...

  10. sysbench做测试

    安装的时候需要libtool,如果已经装了CP到sysbench的目录下 1:用法 sysbench [general-options]… –test=<test-name> [test- ...