WebViewJavascriptBridge 是 iOS 平台很流行的OC 与 JS 交互的第三方框架,作者目前没有支持 Swift ,而本文用到的都是 Swift,所以采取 OC 和 Swift 混编的形式,我没有找到相关的文章介绍用 Swift 使用 WebViewJavascriptBridge,但是我在本文 Demo 使用中没有发现什么问题
最新的 WebViewJavascriptBridge 支持同时支持 UIWeView 和WKWebView ,但是两者使用有一些区别,所以分成两篇文章讲,本文主要是讲 WebViewJavascriptBridge 在 UIWeView 中的基本使用
1.引入 WebViewJavascriptBridge 框架
- 新建一个 Swift 语言的新工程,在工程里新建一个 OC 文件,Xcode 会提示创建一个
Objective-C bridging header
文件,点击Creat Bridging Header
,然后 Xcode 就为工程创建了一个Bridging Header
文件,然后把刚才新建的 OC 文件删掉
- 从 Github 上下载
WebViewJavascriptBridge
, 解压压缩包,把压缩包里面的 WebViewJavascriptBridge 文件夹拖进工程,因为 WebViewJavascriptBridge 是 OC 框架工程,Swift 要使用这个框架需要在Bridging Header
文件里#import "WebViewJavascriptBridge.h"
- 如果上面步骤之后提示错误找不到文件,可以去工程的
Build Settings
的User Header Search Paths
下面设置为${SRCROOT}
和recursive
上面几步完成之后就可以在 Swift 工程里面使用 WebViewJavascriptBridge 了
2. WebViewJavascriptBridge的使用
2.1 创建并初始化 UIWebView
创建 UIWebView 的部分代码:
|
|
注意:这里不要为 UIWebView 设置代理,因为在下一步在创建WebViewJavascriptBridge 的时候,UIWebView 的代理需要赋值给 WebViewJavascriptBridge
2.2 创建并初始化 WebJavaScriptBridge
因为 WebViewJavascriptBridge 实例,在控制器中多个地方用到,因此定义一个全局的变量保存这个实例
|
|
看一下 bridgeForWebView:(id)webView
的内部实现,它最终调用了下面的方法:
|
|
实际上就是内部初始化一个 WebViewJavascriptBridgeBase 对象赋值给 _base
,把外部的 webView
赋值给 内部的 _webView
,并且把 webView
的代理设置为自己
3. JS 和 Swift 的相互调用
3.1 在控制器里注册 JS 要调用的 Native 的方法
先看一下部分示例代码:
|
|
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler
,这个方法是注册一个 Native 的方法给 JS 调用,该方法有两个参数:第一个参数 handlerName,是注册的方法别名;第二个参数 handler,是个 Block,也就是 Native 实现的功能,JS 要调用的 Native 的功能实现其实就是 Block 内的代码功能,并且这个 Block 有两个参数一个参数是 JS 返回给 Native 的参数,另一个参数是一个 Block,调用这个block 可以把 Native 的结果返回给 JS ,而在 JS 代码里面使用 callHandler
调用注册的这个方法,这就实现了 JS 调用 Native 了:
|
|
3.2 Native 调用 JS 的实现
由于 WebViewJavascriptBridge 也是拦截URL来实现的调用原生功能,所以有一些代码跟之前 iOS下JS与Swift互相调用(一)UIWebView拦截URL 中的 HTML 的 JS 代码很相似
HTML 中有一个必须要添加的 JS 方法,然后需要自动调用一次该方法:
|
|
添加完 setupWebViewJavascriptBridge
方法,需要在 JS 中主动调用一次该方法:
|
|
这是 Native 调用 JS 的功能的代码:
|
|
Native 需要调用的 JS 功能,也是需要先注册,然后再执行的,如果Native 需要调用的 JS 功能有多个,那么这些功能都要在上面这个方法了先注册,注册之后才能够被 Native 调用
下面需要好好分析一下 JS 中 setupWebViewJavascriptBridge
这个方法的作用:
首先调用
setupWebViewJavascriptBridge
,第一次执行的时候,由于window.WebViewJavascriptBridge
和window.WVJBCallbacks
都不存在,所以会继续往下执行,将参数callback(它是一个function)装进数组赋值给window.WVJBCallbacks
JS 支持动态添加属性并赋值,这里window.WVJBCallbacks = [callback]
就是动态添加属性并赋值,另外 JS 中的全局变量都可以使用window.xxxx
来调用,动态添加的属性也可以不加window.
,直接使用WebViewJavascriptBridge
帮助 JS 调 用 Native 的 url 有两种,一种是wvjbscheme://__BRIDGE_LOADED__
而另一种是wvjbscheme://__WVJB_QUEUE_MESSAGE__
前者只有在调用setupWebViewJavascriptBridge
的时候执行一次,一般来说这个url 如果没有页面应该只会执行一次;第二种 url 所有 JS 调用 Native 功能时,都会使用到在拦截到自定义的 url 时,
WebViewJavascriptBridge
分了三种情况,如果是wvjbscheme://__BRIDGE_LOADED__
,就往 HMTL 中注入已经写好的 JS ,这个 JS 在WebViewJavascriptBridge_JS
中;如果是wvjbscheme://__WVJB_QUEUE_MESSAGE__
,那就利用stringByEvaluatingJavaScriptFromString
,取回调用 JS 中callHandler
传进去的参数。
然后再从WebViewJavascriptBridge
之前保存的 Native 方法对应的 Block,调用对应的 Block
4.WebViewJavascriptBridge 在 JS 和 Native 相互调用的实现原理
4.1 JS 调用 Native 的原理
从上面第三部分可以看到,JS 和 Native 的相互调用都是需要其中一方注册方法,另一方就可以根据注册的方法名调用到相应的方法
JS 调用 Native 的时候,在 JS 里调用 native 的代码如下:
|
|
这里 callHandler
前的 WebViewJavascriptBridge
,其实就是上一步注入到 JS 中的代码中,动态创建属性,动态赋值的属性,如下代码片段可以在 WebViewJavascriptBridge_JS
中找到:
|
|
而 callHandler
内部调用了另一个 JS function _doSend
,而_doSend
内部其实就是把 handlerName
和参数 data
,再加上callbackId
装成键值对,然后保存到数组 sendMessageQueue
,同时加载一次 wvjbscheme://__WVJB_QUEUE_MESSAGE__
到此利用 WebViewJavascriptBridge
实现 JS 调用 iOS Native 就完成了
4.2 Native 调用 JS 的原理
Native 调用 JS 的功能,也需要先在 JS 中为要调用的功能注册一个别名:
|
|
Native 调用功能的通过别名 handlerName
调用 JS:
|
|
而 callHandler
方法又是如何实现调用 JS 方法的呢?callHandler
内部是将传递给 JS 的参数、handlerName
、callbackId
组合成字典,然后把字典转换成字符串,将转换后的字符串以参数的形式,通过 stringByEvaluatingJavaScriptFromString
传递给 JS ,JS 中将传递过来的字符串转成 json,然后通过 handlerName
获取对应的 function
执行,这是关键的几个代码段:
|
|
下面这里是在 WebViewJavascriptBridge_JS
里面找到 handlerName
对应的 function
,并执行function
|
|
至此利用 WebViewJavascriptBridge 实现 Native 和 JS 相互调用的功能就完成了
5 总结
利用 WebViewJavascriptBridge 来实现 JS 与 Native 的交互的优点:
- 获取参数时,更方便一些,如果参数中有一些特殊符号或者url带参数,能够很好的解析
也有一些缺点: - 做一次交互,需要执行的 JS 与原生的交互步骤较多,至少有两次。
- 需要花较多的时间,理解WebViewJavascriptBridge的原理和使用步骤
原文地址: iOS下JS与OC互相调用(五)–UIWebView + WebViewJavascriptBridge
原文是讨论 OC 与 JS 的交互,我按照作者的思路,用 Swift 实现 Native 与 JS 的交互,这是 代码地址
本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!