美文网首页程序员iOS Developer
WebViewJavascriptBridge原码分析

WebViewJavascriptBridge原码分析

作者: EA88 | 来源:发表于2017-07-18 09:34 被阅读175次

前言

本文主要内容是对iOS的WebViewJavascriptBridge源码进行分析梳理,分为iOS端调用JS端,以及JS端调用iOS端两部分,并在最后进行了总结。

iOS端调用JS端

  1. JS端调用WebViewJavascriptBridgeregisterHandler(handlerName, handler)注册相应的回调,并将handler存到一个messageHandlers的数组当中。

  2. JS端通过将一个隐藏的iframesrc设置为:https://__bridge_loaded__,来触发OC的WebView的回调webView: shouldStartLoadWithRequest: navigationType:,此时会判断该请求的url,如果是上面的的https://__bridge_loaded__,则将WebViewJavascriptBridge的JS代码注入(通过调用UIWebView的stringByEvaluatingJavaScriptFromString:或者WKWebview的stringByEvaluatingJavaScriptFromString:completionHandler:的方法)到网页中。

  3. iOS端调用callHandler:handlerName data:responseCallback:,并将其参数封装成一个WVJBMessage(NSDictionary)并将responseCallback存到responseCallbacks(NSMutableDictionary)中,格式如下:

    message:
    {
        callbackId = "objc_cb_6"; //6是_uniqueId从0,以1为步长累加上来的
        data =     {
            greetingFromObjC = "Hi there, JS!";
        };
        handlerName = testJavascriptHandler; //在js端注册的名字,其对应的是一个方法。
    }
    
    • 向Web端注入JSBridge的JS代码之前先将message保存在一个startupMessageQueue(NSMutableArray)中,待调用injectJavascriptFile向Web端注入JSBridge的JS的时候,递归的执行_dispatchMessage:
    • iOS端调用方法_dispatchMessage:中将message序列化成一个json字符串messageJSON
  4. iOS端接下来会回调UIWebView的stringByEvaluatingJavaScriptFromString:或者WKWebview的stringByEvaluatingJavaScriptFromString:completionHandler:方法执行JS端的代码:WebViewJavascriptBridge._handleMessageFromObjC('messageJSON')

  5. JS端执行WebViewJavascriptBridge._handleMessageFromObjC(),从数组messageHandlers根据上面所说的handlerName取出相应的方法执行,如果iOS端有传入callbackId,则将其变成responseId,和要返回的数据responseData,构造一个message,并写入在sendMessageQueue中,接着将iframesrc设置为:https://__wvjb_queue_message__,这将触发UIWebView的webView:shouldStartLoadWithRequest:navigationType:或者WKWebView的webView:decidePolicyForNavigationAction:decisionHandler:回调方法。

  6. iOS端判断请求是否是https://__wvjb_queue_message__,如果是,则调用flushMessageQueue,从JS端中的sendMessageQueue取出message(json格式),并将其转换成本地的WVJBMessage(NSDictionary),并通过它的responseId从本地的responseCallbacks取出回调方法进行执行。

JS端调用iOS端

  1. iOS端在WebView加载前,调用registerHandler:handler:方法注册回调。这些回调会以注册时传入的方法名为key,存入名为messageHandlers(NSMutableDictionary)中。
  2. JS端调用setupWebViewJavascriptBridge:
    发起一个https://__bridge_loaded__请求(通过设置iframesrc实现)触发iOS端的UIWebView的webView:shouldStartLoadWithRequest:navigationType:或者WKWebView的webView:decidePolicyForNavigationAction:decisionHandler:回调方法,将JSBridge的JS代码注入到网页中。
  3. JS端调用bridge.callHandler(handlerName, data, responseCallback),然后将各个参数封装成一个message,其中会生成一个callbackId来标记这个responseCallback,存入sendMessageQueue中,接着设置iframesrchttps://__wvjb_queue_message__,依次触发UIWebView的webView:shouldStartLoadWithRequest:navigationType:或者WKWebView的webView:decidePolicyForNavigationAction:decisionHandler:回调方法。
  4. iOS端判断请求是否是https://__wvjb_queue_message__,如果是,则调用flushMessageQueue,从JS端中的sendMessageQueue取出message(json格式),并将其转换成本地的WVJBMessage(NSDictionary),并通过它的handlerName从本地的messageHandlers取出回调方法进行执行。
  5. iOS端接着将JS端传入的callbackId变成responseId并和responseData一起构造一个message,然后调用方法_dispatchMessage:中将message序列化成一个json字符串messageJSON
  6. JS端执行WebViewJavascriptBridge._handleMessageFromObjC(),根据responseId从数组responseCallbacks中取出相应的回调执行。

总结

通过上面的分析,我们可以发现:

  • iOS端调用JS接口,通过UIWebView的stringByEvaluatingJavaScriptFromString:或者WKWebview的stringByEvaluatingJavaScriptFromString:completionHandler:的方法既可。但是为了取得取得JS返回的结果,JS必须将结果封装成一个json数据,并写入的sendMessageQueue,然后通过设置一个隐藏的iframesrchttps://__wvjb_queue_message__来触发iOS端的WebView的回调,接着就在回调中调用JS的WebViewJavascriptBridge._fetchQueue()方法,取回要返回的结果信息。

  • JS端调用iOS端的接口,则先将消息写入sendMessageQueue中,然后通过设置一个隐藏的iframesrchttps://__wvjb_queue_message__来触发iOS端的WebView的回调,接着就在回调中调用JS的WebViewJavascriptBridge._fetchQueue()方法,取回要执行的方法的信息,iOS端根据这些信息找到相应的block进行执行,最后将返回的结果转换成json,并调用JS的WebViewJavascriptBridge._handleMessageFromObjC(messageJson)方法将结果回传给JS。

相关文章

网友评论

    本文标题:WebViewJavascriptBridge原码分析

    本文链接:https://www.haomeiwen.com/subject/qkuckxtx.html