WKWebView 新变化:发掘 WKWebView 的神奇妙用

Python实战社群

Java实战社群

长按识别下方二维码,按需求添加

扫码关注添加客服

进Python社群▲

扫码关注添加客服

进Java社群

作者:RyRYanZhong,iOS 开发,字节跳动研发工程师

来源公众号丨老司机技术周报(ID:LSJCoding)

Sessions: https://developer.apple.com/videos/play/wwdc2020/10188/

导览

  1. 更灵活的 JS 控制

  2. 解决 native 与 web 命名空间冲突

  3. 更灵活的 JS 参数传递

  4. web 与 native 双向通讯

  5. 更好的渲染方式

  6. 多个新 api

更灵活的 JS 控制

WKWebView 中, 使用 javaScriptEnabled 可以 disable 所有 webview 试图去加载的 js 文件, 但是因为 native 很多时候其实都需要通过 EvaluateJavaScript 来进行数据交互. 直接禁用 javaScriptEnabled 实际上是非常粗粒度的行为. 因此这个属性将会被抛弃 取而代之的新属性 allowsContentJavaScript, 使用这个属性可以禁用内联的 JS, url 方式加载的远端 js, 以及本地路径的 js 文件, 但是 native 直接执行的 js 仍然有效 在 decidePolicy 代理方法中使用 WKWebpagePreferences, 更可以对每个 web 页面进行更细致的配置, 来决定当前 web 页面是否加载 js 以下图代码为例, 针对特定的 url, 将 allowContentJavaScript 设为 false, 可以使 web 页面更为灵活, 例如在某些特定的页面, 你只希望获得 html 的布局能力, 然后点击交互网络请求等细节交由 native 接管, 这样可以使页面加载更为迅速

解决 native 与 web 命名空间冲突

如上图所示, 例如 native 执行了 js 后将 window.commentDetails 设为 null, 这样会导致 js 内的同名函数直接被置空, 这种 native 与 web 的命名空间冲突问题非常难以察觉, 甚至有恶意的 web 应用会故意覆盖同名函数来达到改变应用行为或者获取用户信息的能力. 要彻底解决, 就需要将 native 的 js 运行环境跟 web 的 js 运行环境进行隔离, 因此 native 需要一个自己的 global object, WKContentWorld 就是为此而生的

如上图所示, 使用方式是在 native 执行 js 的 api 里, 加上 .defaultClient 的参数

更灵活的 JS 参数传递

例如我们希望在 native 侧构建一个完整的 dom 节点并插入到 html 时, 我们需要 hardcode 很多 js 中数据结构的代码

例如下图中的 maring: "0", 这里的 0 在 native 的其他地方其实是 Int 类型, 但因为让这段 js 代码能转 string 从而让 webview 调用, 因此需要 hardcore 成 "0"

为了解决这个问题, 苹果引入了 callAsyncJavaScript api

如上图, 在执行这段 js 时, 这段 js 的 scope 内使用到的变量, 可以直接通过 arguments 这个参数进行传递, 并且可以直接使用 swift 的字典数据类型

上图是一个更神奇的妙用

在这段 js 中 return 了一个 promise 对象, 因此 native 的 completion 会等待这个 promise 被 resolve 了, 才会执行, 并且可以在 native 获取到 fetch 成功后的数据

web 与 native 双向通讯

以上图为例, 这是现有 api 下很常见的 js 和 native 的通讯方式, web 直接调用 webkit 中的 postMessage 来调用 native, 在现有的 webkit 框架下只能实现 web to native 的单向调用, 如果要双向通讯, 则需要开发者在 postMessage 的基础上构建自己的双向通讯机制.

但在新的 WKWebView 中, 苹果加强了 WebView 与 native 的通讯能力, postMessage 在 js 的返回值是从 undefine 变成了 promise 对象

如上图, 在 userContentController 收到 message 后, 可以添加一个 replyHandler 参数, 当你执行这个 replyHandler 时, js 对应的 promise 就会被 resolve

如上图, 在 js 侧就可以通过 promise 的形式获取到这个 replyHandler 的入参并执行后续的逻辑

因此, 这套双向通讯的机制很好地利用了 js 的 promise 异步机制与 swift 的代码块相结合,  比起开发者自己去构建双向通讯机制, 会更为友好和完善

更好的渲染方式

在 css 中, 媒体查询样式可以使得同一份 css 代码在不同的平台运行有不同的展示效果

例如上图的页面, 被标记的 header 和 footer 实际上在 iPhone 上并不希望展示, 因为更多的时候 app 有着自己本身的 header 和 footer, 这个与 web 的 header 和 footer 在 ui 上造成冲突

因此在写 css 的时候, 我们可以通过媒体查询这一特性, 使得 css 在 no-header-and-footer-device 里自动隐藏这些 ui 元素

如上图,  通过 mediaType 这个新的对象属性, 就可以实现 css 媒体查询的自适应

多个新 api

WebView 内容查找

使用上图的 find api, 可以使 WebView 直接选中并滚动到对应的区域

生成 PDF

使用上图的 createPDF api, 可以截图整个 WebView 的全部内容, 包括屏幕外的, 并作为 pdf 输出

Archive Web Content

使用上图的 createWebArchiveData api, 可以为当前页面的所有数据创建一个 snapshot, 包括整个页面的 html, js, css 以便重新运行这个 ArchiveData 时, 可以重现当时 Web 页面的所有内容, 因此也非常适用于 Debug

APP-bound domains

例如上图的 web content 中, 出现了一个外部的 url, 我们希望用户能在浏览器中跳转到这个 url, 但同时我们不希望用户在这个新的 web 页面中, 信息被泄露或者遇到其他安全问题, 按苹果的描述, 使用 APP-bound domains 可以使得浏览器在指定 domain 以外的 web 应用中, 禁止它们与用户有 deep interaction, 不过具体没有说明会禁止什么行为 要使用这一能力, 我们需要在 info.plist 中增加自己的 domain 白名单

总结

今年的 WebKit 更新, 个人感觉苹果升级了更多 js 与 native 的交互能力, 充分运用的话能使得我们的 hybrid 应用的代码有很好的简化.

程序员专栏 扫码关注填加客服 长按识别下方二维码进群

近期精彩内容推荐:  

 再见!深圳!再见!腾讯!

 疯传朋友圈的 Pony 马化腾的讲话

 SpringBoot 实现并发登录人数控制

 异步 Python 比同步 Python 快在哪里?

在看点这里好文分享给更多人↓↓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值