美文网首页
发掘 WKWebView 的神奇妙用

发掘 WKWebView 的神奇妙用

作者: 猪猪行天下 | 来源:发表于2020-12-08 09:38 被阅读0次

    文章转载自这里

    导览

    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 接管, 这样可以使页面加载更为迅速

    图片.png

    解决 native 与 web 命名空间冲突

    图片a.png

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

    图片b.png

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

    更灵活的 JS 参数传递

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

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

    图片c.png

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

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

    上图是一个更神奇的妙用

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

    web 与 native 双向通讯

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

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

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

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

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

    更好的渲染方式

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

    图片y.png
    例如上图的页面, 被标记的 header 和 footer 实际上在 iPhone 上并不希望展示, 因为更多的时候 app 有着自己本身的 header 和 footer, 这个与 web 的 header 和 footer 在 ui 上造成冲突
    图片z.png
    因此在写 css 的时候, 我们可以通过媒体查询这一特性, 使得 css 在no-header-and-footer-device 里自动隐藏这些 ui 元素
    图片q.png
    如上图, 通过mediaType这个新的对象属性, 就可以实现 css 媒体查询的自适应

    多个新 api

    WebView 内容查找

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

    生成 PDF

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

    Archive Web Content

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

    APP-bound domains

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

    总结

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

    推荐阅读

    用 Web 技术为 Safari 编写扩展

    Universal Links 新变化:让触达更广更快

    相关文章

      网友评论

          本文标题:发掘 WKWebView 的神奇妙用

          本文链接:https://www.haomeiwen.com/subject/afhfgktx.html