前言
Hybrid App(混合模式移动应用)是指介于web-app、native-app这两者之间的app,兼具“Native App良好用户交互体验的优势”和“Web App跨平台开发的优势”。谈到Hybrid App,JS与Native code的交互就是一个绕不开的话题,这时就需要“一座桥”来连接两端。JSBridge
架起了一座连接JavaScript
与Native Code
的桥梁,让两端可以相互调用。
本文基于UIWebView
,将会分别介绍3种方案。通过Iframe
、Ajax
、JSCore
来实现JSBridge,涉及到的Demo地址,顺手给个Star呗😏。
实现方案
Iframe
废话不多说,直入主题,首先讲的这种方案比较常见。WebViewJavascriptBridge
与Cordava
都是采用的该方案(推荐看看我之前的文章Cordova源码解析)。
核心思路就是在UIWebView拦截Iframe的src,双方提前约定好协议,例如https://__jsbridge__
就是一次调用开始。
可以学习Cordova
的策略,将并发的多次调用打包合并为一次处理,可以优化性能。
实现
1.JS暴露一个方法给Native,接收执行结果
1 | function responseFromObjC(response) { |
2.Native实现UIWebView
的代理,在webView:shouldStartLoadWithRequest:navigationType:
方法拦截请求,识别到特定URL,开始一次调用流程。
1 | // 拦截JS调用原生核心方法 |
3.JS开启一个Iframe,加载一个特定的URL,开始一次调用
1 | var iframe = document.createElement('iframe'); |
4.Native方法执行完成后,调用JS方法responseFromObjC
将结果回传给JS。
1 | ... |
PS:demo代码为了简化,直接将参数放在URL的query里,如果只传输一些简单数据是没有问题的,更好的方案是JS先将参数存放起来,通过URL传递一个key给Native,再暴露一个通过key取数据的方法,Native主动调用这个方法取。
Ajax
第二种方案是JS使用XMLHttpRequest
发起请求,在Native拦截达到调用的目的。通过自定义NSURLProtocol
可以拦截到Ajax请求。Demo里有详细的代码和注释,建议结合Demo一起看。
实现
1.新建类继承自NSURLProtocol
,并注册。
1 | [NSURLProtocol registerClass:[CRURLProtocol class]]; |
2.实现自定义NSURLProtocol
,在startLoading
方法拦截Ajax请求
1 | - (void)startLoading { |
3.JS发起Ajax请求,URL为提前约定的特殊值,例如:http://jsbridge。请求参数放在Request Body
里。
1 | // 调用原生 |
4.Naive拦截到请求,获取参数,执行Native方法,最后通过Ajax的Response
把结果返回给JS。
1 | ... |
JSCore
前两种方案虽然实现方法不一致,但是思路都是类似的,由于JS不能直接调用Native方法,通过曲线救国的方式,找到一个载体来传递信息。
第三种方案就比较直接了,使用iOS7推出的黑科技JavaScriptCore
,将Native方法直接暴露给JS,打通两端的数据通道。谈到JavaScriptCore
不得不说的是bang590的JSPatch
,还有ReactNative、Weex等都是利用JavaScriptCore
来实现各种炫酷的功能。(强力推荐一本Lefe_x的书《一份走心的JS-Native交互电子书》,非常精彩)。
不过这种方案有个缺陷,UIWebView
没有暴露JSContext
,虽然可以通过KVC拿到,但是毕竟不是一种完美的解决方案,不知道上架会不会有风险(求知道的同学指教一下)。
实现
实现流程就不细说了,流程比较简单,Demo里面有。说说关键实现代码
1 | - (void)injectJSBridge { |
JS调用非常简单,一句话搞定。
1 | callNative("alertMessage", "Hello world!") |
性能对比
为了验证三种方案的性能,设计了个简单的实验,分别执行了100、1000、10000次调用,测试手机iPhone X,系统iOS 12,时间对比如下图所示。
先说结论,JSCore的性能是最优的,JSCore>Ajax>Iframe
。在低并发的时候三种方案差距不大,执行次数10000次时Iframe效率就很低了,Ajax次之,JSCore性能很稳定。当然实际使用的时候不会出现调用10000次这种极限情况。Cordova
对于并发有个优化策略,很值得参考,将并发的多次调用打包合并为一次处理。