程序员iOS Developer

WebViewJavascriptBridge原码分析

2017-07-18  本文已影响175人  EA88

前言

本文主要内容是对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中取出相应的回调执行。

总结

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

上一篇 下一篇

猜你喜欢

热点阅读