笔记:iOS 与 JavaScript 的交互(一)UIWebView


 拍摄于 2017-02-09
拍摄于 2017-02-09

UIWebView

笔记内只涉及单独使用 UIWebView 与 JavaScript 交互的内容。 UIWebView 还可以和 JavaScriptCore 配合使用, 对应内容会在之后以 JavaScriptCore 为主题的笔记中。

基本的页面加载、交互

以打开、关闭作为例子。但还包括了前进 goBack、回退 goForward 、重新加载 reload、停止加载 stopLoading 等方法,或者:是否正在加载 isLoading、是否可以回退 canGoBack、是否可以前进 canGoForward 这样的属性。可以自行查询文档进行了解。

加载在线网页

加载在线网页。

加载本地页面

打开一张本地的 html 文件。

原生调用 JavaScript

直接使用 string​By​Evaluating​Java​Script(from:​)

使用 string​By​Evaluating​Java​Script(from:​) 方法,就可以在原生中通过如下方法来调用。

这里通过 webViewDidStartLoad 委托(delegate,下同),在页面开始加载的时候触发对应的 JavaScript。

假设加载的页面引入的 JavaScript 包含如下三个函数,在原生里就可以通过对应的方法进行调用、获取返回值。

注入 JavaScript

同时 Xcode 的 console 中会打印 returned value from JavaScript: hello Lien。

不确定是不是约定促成这里该用「注入」这个词,具体的调用方法不变仍使用 string​By​Evaluating​Java​Script(from:​),主要的区别在于:加载一个远程别人的网站网页,可以从我们当前系统本地(Bundle.main)对对方网页注入一段 JavaScript,使得原生中对加载的网页做一些优化修改。

演示中的操作:

  1. 加载一个本地文件夹中的 index.html;
  2. index.html 本身引入了 index.css 和 index.js;
  3. 当这个三个文件加载完毕,再使用 UIWebView 的方法来加载一个 file.js 文件。

JavaScript 调用原生

UIWebView 拦截请求,实现 JavaScript 从内部调用外部的原生。

如果把原生调用 JavaScript 看作是由外至内的调用,那么相反、由内至外的使用 UIWebView 来使 JavaScript 调用的官方方法是没有的。而 JavaScript 调用原生方法之所以成立,实际上是通过外部拦截拦截内部的请求1。

比如说在加载完毕的 html 中有以下这样一个链接

要在原生中拦截到这个 hello://lien 的具体的代码就如下

这里在函数中的操作是:

  1. 拦截名为 hello 协议;
  2. 获取协议后的 path,也就是lien;
  3. 将 path 的 string 作为 window.alert() 方法的参数,通过 webview.stringByEvaluatingJavaScript() 方法执行该 JavaScript 函数;
  4. 因为拦截到了对应的hello 协议,在委托方法里最后返回 false,阻止 UIWebView 继续执行该请求(跳转了也是个 404)。

JavaScript 调用原生的单独演示

首先是 html 中一个的按钮。

JavaScript 来给按钮进行对时间进行监听。

接着我们需要一个对于创建 <iframe> 的分装方法。

然后是具体的回调函数。

最后,是 iOS 中对应的方法2。


  1. 对这一块内容更加详细的说明可以参考腾讯 Bugly 的这篇:解耦—Hybrid H5跨平台性思考 ↩︎

  2. 将 url.query 解析成 Dictionary<String:String> 可以参考这里,获取 url.query 中一个 param 对应的 value 可以参考这里,还有对 url 进行 encode 和 decode 可以参考这里 两个相关 API: addingPercentEncoding(withAllowedCharacters:) 、 removingPercentEncoding。 ↩︎

感谢阅读

你们好, 2018 年初把小站从 Jekyll 迁移到 Hugo 的过程中,删除了评论区放的 Disqus 插件,考虑有二:首先无论评论、还是对笔记内容的进一步讨论,读者们更喜欢通过邮件、或者 Twitter 私信的方式来沟通;其次一年多以来 Disqus 后台能看到几乎都是垃圾留言(spam),所以这里直接贴一下邮件、以及 Twitter 账户 地址。

技术发展迭代很快,所以这些笔记内容也有类似新闻的时效性,不免有过时、或者错误的地方,欢迎指正 ^_^。

BEST
Lien(A.K.A 胡椒)
本站总访问量次 本站总访客量次 本文总阅读量次