iOS 原生与 JavaScript 的交互方式很多,目前我知道的大概有以下几种:
在JS 中做一次URL跳转,然后再拦截跳转(这里分为UIWebView 和 WKWebView两种)
利用WKWebView 的MessageHandler
利用系统库JavaScriptCore(iOS7 推出的)
利用第三方库WebViewJavascriptBridge
利用第三方cordova库,以前叫PhoneGap
现在最热门的React Native
这篇文章主要是介绍 UIWebView 拦截 URL 的方式与 JS 交互,如果 iOS 与原生的交互比较少或者简单,完全可以使用这种方式
1. 创建UIWebView,并加载本地HTML
为了测试方便,这里是从本地加载HTML文件,真实情况肯定是从网络加载HTML网页
|
|
本地的HTML文件里面定义了一些按钮,来触发调用原生的方法,然后再将执行结果回调到JS里
|
|
下面是部分JS代码
|
|
JS代码解释:
为什么自定义一个loadURL 方法,不直接使用window.location.href?
答:因为如果当前网页正使用window.location.href加载网页的同时,调用window.location.href去调用OC原生方法,会导致加载网页的操作被取消掉
同样的,如果连续使用window.location.href执行两次OC原生调用,也有可能导致第一次的操作被取消掉。所以我们使用自定义的loadURL,来避免这个问题
loadURL的实现来自关于UIWebView和PhoneGap的总结一文为什么loadURL 中的链接,使用统一的scheme?
答:便于在OC 中做拦截处理,减少在JS中调用一些OC 没有实现的方法时,webView 做跳转。因为我在OC 中拦截URL 时,根据scheme (即haleyAction)来区分是调用原生的方法还是正常的网页跳转。然后根据host(即//后的部分getLocation)来区分执行什么操作。
为什么自定义一个asyncAlert方法?
答:因为有的JS调用是需要OC 返回结果到JS的。stringByEvaluatingJavaScriptFromString是一个同步方法,会等待js 方法执行完成,而弹出的alert 也会阻塞界面等待用户响应,所以他们可能会造成死锁。导致alert 卡死界面。如果回调的JS 是一个耗时的操作,那么建议将耗时的操作也放入setTimeout的function 中
2. 拦截URL
在UIWebView的代理方法,可以拦截到每一个链接的Request,返回 true,webView 就会加载这个链接;返回 false,webView 就不会加载这个链接,我们就在这个拦截URL的代理方法中通过 scheme 处理自己定义的URL
|
|
然后根据不同 host 执行不同的 Native 代码
|
|
3. JS和Swift的相互调用
JS调用Swift的原生方法,并且将结果返回给JS:
|
|
有时候我们在JS中调用Swift方法的时候,也需要传参数到Swift中,怎么传呢?JS自定义的URL就像一个 get 请求一样,把参数放在后面:
|
|
所有的参数都在URL的query中,获取这些参数需要先通过&将字符串拆分,在通过=把参数拆分成key 和实际的值:
|
|
3. Swift调用JS注意
将Swift执行结果返回给JS 需要注意:
如果回调执行的JS 方法带参数,而参数不是字符串时,不要加单引号,否则可能导致调用JS 方法失败。比如我这样的:
另外,利用webView.stringByEvaluatingJavaScript(from: "var arr = [3, 4, 'abc']")
,可以往HMTL的JS环境中插入全局变量、JS方法等
原文地址: iOS下 JS 与 OC 互相调用(一)–UIWebView 拦截URL
原文是讨论 OC 与 JS 的交互,我按照作者的思路,用 Swift 实现 Native 与 JS 的交互,这是 代码地址
本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!