webview javascript bridge

在hybrid iOS app中,为了达到有些页面能够方便的通过服务器配置内容更改客户端界面,而不需要等待苹果的一个审核周期,一种简单的办法就是把这样的界面用UIWebView通过读取服务端的H5来展示。如果除去简单的展示功能,还希望能做更复杂的事情,调用一些native的模块完成一些操作,甚至进而将操作结果展示在H5页面上,就需要借助webview javascript bridge的帮助了。
最近借用了这个bridge完成了一个H5页面上的图片全屏浏览,左右滑动,长按保存的功能。

两个基础API

WebviewJavascriptBridge是github上的开源库,它可以做到js与native互相发送消息并且返回结果。它主要是基于iOS UIWebView的两个方法来完成js和native之间的通信的,这两个API是整个通信机制的基石:

    //UIWebView
    func stringByEvaluatingJavaScriptFromString(script:String)->String

    //UIWebViewDelegate
    func webView(_ webView:UIWebView, shouldStartLoadWithRequest request:NSURLRequest, navigationType navigationType:UIWebViewNavigationType) -> Bool

通过第一个API,native可以向js发消息,这很简单而js端要想向native发消息,就必须借助一点黑魔法。这里js和native端约定好一个fake protocol,在js中创建一个空的iframe,这个frame通过设置src来读取这个fake address,而这个读取请求则会被UIWebViewDelegate的代理方法截获,并且当成发送给native端的消息去解析。

 var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'

 function _createQueueReadyIframe(doc) {
  messagingIframe = doc.createElement('iframe')
  messagingIframe.style.display = 'none'
  messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
  doc.documentElement.appendChild(messagingIframe)
 }

此后每次js想要通知native端接收消息,都会设置这个messagingIframe的src。

js向native发消息的过程

native端初始化

为了响应js端发来的消息,native端在初始化加载H5的UIWebView的时候需要做一些准备工作:

  1. 初始化一个WebviewJavascriptBridge实例,这里需要注册一个默认的响应函数,还可以用registerHandler方法以key-block的形式注册若干handler,其本质类似于向js端暴露若干函数,key相当于函数的声明,block相当于函数的实现。这里我们注册了一个browseImages的方法,block中就是调用图片浏览的模块用paging的UIScrollView去展示图片。
  2. UIWebView可以去加载H5啦
  3. 在UIWebView加载完毕的delegate method回调中,注入js,包括WebviewJavascriptBridge的js和我们自己定义的js。以我们的需求为例,在这里需要给所有的image节点加上listener,当图片上发生点击事件的时候,去通过bridge向native端发送browseImages的消息。

实际流程

虽然上面说明了如果在js端如何向native端发送消息,但是仍有两个问题需要解决:

  1. 参数,尤其是复杂的参数如何传递
  2. 回调,如果能够异步处理另一端的处理结果

第一个问题的答案是js端将调用函数,参数,回调block都保存到了sendMessageQueue中,native端收到了消息后,会主动来取参数。
第二个问题的答案是为回调block生成callbackid,保存callbackid和回调block到字典中,在回调消息中去和responseid做匹配。
那么,2还带来了一个延伸问题,虽然有以上两个API保证了互相传递的通道,但是如何区分是另一方主动发来的调用还是回调的通知呢?
这就是通过判断是否存在responseid这个字段来判定的。

详细流程如下,左侧代表js端,右侧代表native端:

流程1

流程2

流程3

native端向js端发消息

总体来说流程是完全类似的,这次用文字来描述:

  1. js端首先注册若干handler方法,保存在messageHandlers字典中
  2. native端发起对js的调用:将调用的js handler名称,参数放到message字典中
  3. 如果需要回调,则为回调方法生成唯一的callbackId,将callbackId和回调block保存在native端的responseCallbacks字典中
  4. 通过UIWebView.stringByEvaluatingJavascript...调用js端处理message函数
  5. js端检查发现message中不包含responseId,确认不是js调用native后的回调,则在自己的messageHandlers中找到对应的handler
  6. 如果message中包含callbackId,则生成回调native的block,callbackId在回调message中的key是responseId
  7. handler运行完成,如果需要回调native端,则将生成的数据加入回调message字典中。(现在字典中包含两个key:responseId和responseData)
  8. 将message放到sendMessageQueue中,然后用预定义的protocol设置空iframe的src
  9. native端收到shouldStartLoad.....调用,通过evaluateJavascript...获取sendMessageQueue中的message
  10. 发现message中包含responseId,确认为自己主动发起的调用的回调
  11. 从responseCallbacks字典中根据responseId找到对应的block,用message中的responseData调用,整个流程完成。

end

整个bridge的库,基于底层两个互相通信的方法,实现了一整套优雅的机制,写的真是太棒了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容