转载自: http://www.jianshu.com/p/90a90bd13aac

UIWebView 之痛

开发App的过程中,常常会遇到在App内部加载网页,通常用UIWebView加载。而这个自iOS2.0开始使用的Web容器一直是开发的心病:加载速度慢,占用内存多,优化困难。如果加载网页多,还可能因为过量占用内存而给系统kill掉。各种优化的方法效果也不那么明显,常见的优化缓存方式:
1、尽量使用 GET 请求,iOS 系统 SDK 会自动帮你做缓存。你需要的仅仅是设置下内存缓存大小、磁盘缓存大小、以及缓存路径。只要设置了这两行代码,基本就可满足80%的缓存需求。

设置缓存.jpg

2、Web资源离线加载,热更新资源,完成另外20%的缓存需求(Hybrid框架的Web部分)。
可是无数开发者尝试自己做一个“简陋而脆弱的”系统来实现网络缓存的功能,效果往往是事倍功半 。

初识 WKWebView

UIWebView从 iOS2 就有,iOS8 以后,苹果推出了新框架 WebKit,提供了替换 UIWebView 的组件 WKWebView。各种 UIWebView 的性能问题没有了,速度更快了,占用内存少了,体验更好了,下面列举一些其它的优势:
1、在性能、稳定性、功能方面有很大提升(加载速度,内存的提升谁用谁知道)
2、更多的支持 HTML5 的特性
3、官方宣称的高达60fps的滚动刷新率以及内置手势
4、Safari 相同的 JavaScript 引擎
5、将 UIWebViewDelegate 与 UIWebView 拆分成了14类与3个协议,包含该更细节功能的实现。
相比之下,WKWebView 复杂得多,一些常用API如下:

容器相关

WKWebView.jpg

JavaScript 配置相关

JavaScript API.jpg

存储相关(只支持iOS9以上)

存储类型.jpg

存储 API.jpg

页面加载相关

WKWebView loadRequest.jpg

代理相关

WKNavigationDelegate.jpg

看完API以后,要掌握 WKWebView 并不难,难的是如何处理iOS版本碎片化兼容问题。

性能对比测试

都说提高多么多么大的性能,实测告诉你 WKWebView 的性能有多好,下面用实际项目做个对比测试:
UIWebView 首次加载 www.58.com 首页,耗时 0.0154584ms,内存消耗 24.1 MB

UIWebView耗时.jpg

UIWebView内存消耗.jpg

WKWebView 首次加载 www.58.com 首页,耗时 0.013875ms,内存消耗仅 6.4 MB

WKWebView耗时.jpg

WKWebView内存消耗.jpg

结论:加载耗时差别不大,WKWebView 的内存优化减少了几乎4倍,更重要的是,无论 WKWebView 跳转多少 Web 页面都没有内存泄漏了。WKWebView 使用和 Safari 相同的 Nitro JS 引擎性能,对HTML5性能也提升了4倍。

WKWebView 之坑

新技术的出现必然会或多或少的瑕疵,WKWebView 也不例外。

1、关于缓存

在 WKWebsiteDataStore 出现之前(iOS 9 中),WKWebView 是没有缓存,也无从清理。WKWebView 是基于 WebKit 框架的,它会忽视先前使用的网络存储 NSURLCache, NSHTTPCookieStorage, NSCredentialStorage等,它也有自己的存储空间用来存储cookie和cache,其他的网络类如NSURLConnection 是无法访问到的。 同时WKWebView发起的资源请求也是不经过NSURLProtocol的,导致无法拦截或自定义新请求。
体验过 WKWebView 的一定会遇到修改了H5页面,APP打开时却没有即时更新的问题(实在是缓存得太好了),iOS 8的时候只能增加时间戳的方式解决这个问题(调试下使用,生产环境就只能要求前端修改Cache-Controll了),如下:

时间戳更新.jpg

iOS 9以后终于可以使用 WKWebsiteDataStore 来清理缓存。后来Google一下,又发现iOS 8可以通过清理 Library 目录下的 Cookies 目录来清除缓存,于是

清除WKWebView缓存.jpg

缓存清理的坑趟过了,喜大普奔。

2、关于 Cookie

在使用 UIWebVIew 的时候我们并不关注 Cookie,因为在调用登录接口的时候无论是AFNetworking,还是其他,登录成功之后都会自动保存在
[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies 中,以后再使用也会自动去获取(这里有个 UIWebView 的坑:访问的链接越多,如不处理Cookie,它会加载越来越多的无效 Cookie 导致内容急剧增大)。但 WKWebView 的存储体系与 UIWebVIew 完全不一样,只能手动给它添加 Cookie,如下:

WKWebView设置cookie.jpg

但即便如此,Cookie 还是会偶现丢失的问题,最终只好采用每次 Web 开始加载之时判断 Cookie 是否存在,否则手动添加重新加载,如下:

WKWebView设置cookie.jpg

Cookie 获取的坑趟过了,再次喜大普奔。

3、关于跨域

WebKit框架对跨域进行了安全性检查限制,不允许跨域,比如从一个 HTTP 页对 HTTPS 发起请求是无效的(有一个界面要跳到支付宝页面去支付,死活没反应)。而系统的 Safari ,iOS 10出现的 SFSafariViewController 都是支持跨域的,因此解决办法如下:

跨域跳转.jpg

对于自身域名,还是建议全站 HTTPS 化吧(大势所趋)。

4、关于 JavaScript 交互

UIWebView 使用的 JavaScriptCore 框架,交互时为 JavaScript 运行的上下文环境 JSContext 注入对象 Bridge;WKWebView 使用的 WebKit 框架,交互时为 webkit.messageHandlers 注入对象,如下:

JavaScript注入.jpg

前端H5需要做判断两种不同注入方式带来的不同调用方式:

js调用.jpg

5、关于 NSURLProtocol 拦截

WKWebView 基于 WebKit 框架,与 UIWebView 机制不同:加载过程中所有的请求都不经过 NSURLProtocol,换句话说就是 WKWebView 无法拦截响应数据 鉴于之前大部分 Hybrid 框架的离线预加载机制都依赖于拦截功能,这意味着废掉很多程序猿们辛辛苦苦设计实现的 Hybrid 框架(内功尽失,感觉身体被掏空),再加上 WKWebView 自身的坑不少,因此很多团队都不会轻易替换掉 UIWebView。拥抱变化吧,WKWebView 迟早会取代 UIWebView 成为最佳 Web 容器(iOS 9带来的 SFSafariViewController 更是武功全废,啥都干不了,只能干瞪眼)。

那么问题来了,如何设计新的 Hybrid 框架呢?此处出门左转,点击文章开头进入公众号历史文章,查看《通用Web&Native交互协议设计方案》。

6、关于 POST 请求

简书 http://www.jianshu.com/p/403853b63537 中有关于这个坑的具体描述,笔者这里就不再做研究,这里只说明怎么趟过的坑:使用通用的 Web&Native 交互协议,为 Web 提供 Native POST 请求的接口+回调 CallBack 即可,参见 关于 JavaScript 交互

7、关于本地 HTML 加载

当使用 loadRequest 来读取本地 Documents 目录的 HTML 文件时,WKWebView 是无法读取成功的,只能通iOS 9的新接口加载

load loacl html.jpg

但是在iOS9以下的版本是没提供这个便利的方法的,解决办法:先将本地 HTML 文件的数据 copy 到 tmp 目录中,然后再使用 loadRequest 来加载。但是如果在 HTML 中加入了其他资源文件,例如 js,css,image 等也必须一同 copy 到 tmp 中,这个是非常蛋疼的事情了。然而还有更蛋疼的事:iOS 8下还必须 copy 到 tmp 的 www 目录下 WKWebView 才能读取(Word天,心中千万只草泥马狂奔而过)。参见 http://stackoverflow.com/questions/24882834/wkwebview-not-loading-local-files-under-ios-8

8、关于捏合手势

很多人都喜欢使用 UIWebView 的捏合手势来进行放大和缩小,观看 Web 内容,但 WKWebView 在手机上不支持,却支持其他iOS设备(草泥马再次狂奔而过)。

不支持捏合手势.png

写在最后

当时选择 WKWebView 就是为了提高性能,但是没有想到遇到这么多坑,真是我待 WKWebView 如初恋,WKWebView 虐我千百遍,兴许还有许多未知的坑,欢迎大家留言补充。谢谢支持!

文/zyl04401(简书作者)
原文链接:http://www.jianshu.com/p/90a90bd13aac
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

WKWebView从入门到趟坑相关推荐

  1. web td不对齐_珍稀干货!阿里 Web 音视频开发趟坑指南

    作者 | 阿里文娱前端技术专家 归影 责编 | 夕颜 出品 | CSDN(ID:CSDNnews) 这不是一篇基于MSE开发Web播放器的入门文章,而是围绕Web播放器开发遇到的常见问题与解决方案,毕 ...

  2. 珍稀干货!阿里 Web 音视频开发趟坑指南

    作者 | 阿里文娱前端技术专家 归影 责编 | 夕颜 出品 | CSDN(ID:CSDNnews) 这不是一篇基于MSE开发Web播放器的入门文章,而是围绕Web播放器开发遇到的常见问题与解决方案,毕 ...

  3. 第六期.Net开源社群联合分享--除了情结和价格,Azure最适合什么场景?等你来讲趟坑的实战经验!

    嘿嘿,大家好啊!好荣幸啊这一期,能够咱们.NET开源社区一块来做这次线上分享会. 我就是各位小伙伴可爱而且博学而且低调而且人见人爱花见花开而且谦虚但是经常口不择言的主持人老板娘Grace. 这次有新朋 ...

  4. docker build 变量_Docker从入门到掉坑(二):基于Docker构建SpringBoot微服务

    在之前的文章里面介绍了如何基于docker容器部署一些常见的基础环境,例如MySQL.Redis这些,那么这篇文章里面我会介绍一些关于SpringBoot如何打包运行到docker容器中. 先介绍一下 ...

  5. docker springboot读取配置文件_Docker从入门到掉坑(三):容器太多,操作好麻烦

    前边的两篇文章里面,我们讲解了基于docker来部署基础的SpringBoot容器,如果阅读本文之前没有相关基础的话,可以回看之前的教程. Docker 从入门到掉坑​mp.weixin.qq.com ...

  6. jzy3D从入门到弃坑_4尝试使用jzy3D1.0画图失败

    jzy3D从入门到弃坑_4 尝试使用jzy3D1.0画图失败 觉得有用的话,欢迎一起讨论相互学习~ 记录一下使用jzy3D1.0失败 究其原因在于 本人才疏学浅,对于JAVA openGL真的是一窍不 ...

  7. jzy3D从入门到弃坑_2使用jzy3D0.9画2D散点图

    jzy3D从入门到弃坑_2 使用jzy3D0.9画2D散点图 觉得有用的话,欢迎一起讨论相互学习~ 在上一节中安装jzy3D 0.9版本并且运行了3D的例子 https://blog.csdn.net ...

  8. jzy3D从入门到弃坑_3使用jzy3D0.9画2D散点图--多条线条

    jzy3D从入门到弃坑_3 使用jzy3D0.9画2D散点图–多条线条 觉得有用的话,欢迎一起讨论相互学习~ 主要思路 将多个线条的二维数组读入Scatter对象 存入到同一个画布中 存入多个Scat ...

  9. 学习方法 | 玩开源如何具有“趟坑” 的意识?

    阿木每周会做很多技术分享,AirSim教程,ROS小知识各种栏目.但我们发现,"授人以鱼不如授人以渔",我们希望讲更多学习方法.在之前的科研杂谈也分享过很多研究生阶段的学习方法和科 ...

最新文章

  1. 关于spring中commons-attributes-compiler.jar的使用问题
  2. python拆堆和堆叠的操作_python - 如何合并不同的DFS并堆叠值? - 堆栈内存溢出
  3. liunx系统中的盘符能修改嘛_装系统教程!如何从U盘启动(中)!小白也能变装机大神!...
  4. fastText中常见问题汇总
  5. 郑州志泽网络科技--SSH模拟试题
  6. 【NLP】毕设学习笔记(八)“前馈 + 反馈” = 循环神经网络RNN
  7. @PropertySource读取properties属性 中文乱码问题
  8. 为了有一些储蓄,把自己压榨到最狠的时候是怎样的?
  9. 操作系统—多生产者多消费者问题
  10. Java EE 8停步不前:Java社区能否扭转乾坤?
  11. REST笔记(三):一种标准的超媒体格式:Atom
  12. 垂直旋转转台电机选型_高精密YRT转台轴承概览
  13. 使用jxls导出报错:Connot load XLS transformer please make sure a Transformer implementation is in classpath
  14. MacOS Big Sur 11.4 (20F71) OC 0.7.0 / Cl 5135 / PE 三分区原版黑苹果镜像
  15. 乐优商城(04)--商品规格
  16. 某公司电子商务网站策划方案
  17. 【javascript】字符串逆序输出
  18. android JavaMail报错:SendFailedException: No recipient addresses
  19. 张俊林:当前炼制“大语言模型”的两个现象
  20. 硬件测试工程师养成日记第一篇

热门文章

  1. 土是独体字结构吗_什么叫独体结构
  2. LOJ #6672. 「XXOI 2019」惠和惠惠和惠惠惠(生成函数,整式递推)
  3. python之模拟登录与表单交互
  4. python colorama_Python colorama 模块 使用 说明
  5. openwrt-19.07.2增加EC20支持qmi拨号
  6. 《大型网站技术架构:核心原理与案例分析》拜读总结,第八章——固若金汤:网站的安全架构
  7. 酷我音乐爬虫(400多行代码)
  8. 云发单详细使用视频教程
  9. 【Vijos】1431 守望者的逃离
  10. 技术分享 | 客户分类管理模型在行业中的实践