WebViewJavascriptBridge 原理

WebViewJavascriptBridge 原理官方 demo 交互流程 1 webview 加载 ExampleApp html ExampleApp html 中的 js 代码 functionsetu callback if window WebViewJavas returncallba WebViewJavas

官方demo 交互流程

1.webview 加载 ExampleApp.html

 // ExampleApp.html 中的js代码 function setupWebViewJavascriptBridge(callback) { 
    if (window.WebViewJavascriptBridge) { 
    return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { 
    return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; //创建iframe 梦开始的地方 var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'https://__bridge_loaded__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { 
    document.documentElement.removeChild(WVJBIframe) }, 0) } 

2.创建 一个 iframe 来触发 原生webView的代理方法,即:

// UIWebView - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 
   } //WKWebView - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { 
   } 
上述两个代理方法调用的核心方法如下:
 //判断是否是自己的声明的scheme if ([_base isWebViewJavascriptBridgeURL:url]) { 
    //是否是 'https://__bridge_loaded__' 这个类型的url //如果是 就去加载 WebViewJavascriptBridge_JS.m 中的js代码 if ([_base isBridgeLoadedURL:url]) { 
    [_base injectJavascriptFile]; } else if ([_base isQueueMessageURL:url]) { 
    NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; [_base flushMessageQueue:messageQueueString]; } else { 
    [_base logUnkownMessage:url]; } return NO; } 

到此为止是为了把WebViewJavascriptBridge_JS.m 中的js代码注入Dom中


Native call js

- (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { 
     NSMutableDictionary* message = [NSMutableDictionary dictionary]; if (data) { 
     message[@"data"] = data; } //如果有回调 生成一个callbackId存到message里,并把回调存到全局变量responseCallbacks if (responseCallback) { 
     NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; self.responseCallbacks[callbackId] = [responseCallback copy]; message[@"callbackId"] = callbackId; } } // oc调用网页js方法 是通过WebViewJavascriptBridge._handleMessageFromObjC('%@') // 给js传了一段json  - (void)_dispatchMessage:(WVJBMessage*)message { 
     NSString *messageJSON = [self _serializeMessage:message pretty:NO]; ... NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; //主线程调用 [self _evaluateJavascript:javascriptCommand]; } 

再看 _handleMessageFromObjC()的实现

//处理来自oc发过来的message(json) function _doDispatchMessageFromObjC() { 
     //解析oc传过来的json var message = JSON.parse(messageJSON); var messageHandler; var responseCallback; //js调用oc oc有回调 if (message.responseId) { 
     responseCallback = responseCallbacks[message.responseId]; if (!responseCallback) { 
     return; } responseCallback(message.responseData); delete responseCallbacks[message.responseId]; } else { 
     //oc调用js js有回调 if (message.callbackId) { 
     var callbackResponseId = message.callbackId; responseCallback = function(responseData) { 
     _doSend({ 
     handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); }; } var handler = messageHandlers[message.handlerName]; if (!handler) { 
     console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); } else { 
     //调用已在 messageHandlers中注册的方法, 回调给responseCallback->_doSend //_doSend 即js调用oc  handler(message.data, responseCallback); } } } 

js call oc

调用流程: WebViewJavascriptBridge.callHandler() -> _doSend()

 function callHandler(handlerName, data, responseCallback) { 
      if (arguments.length == 2 && typeof data == 'function') { 
      responseCallback = data; data = null; } _doSend({ 
      handlerName:handlerName, data:data }, responseCallback); } // 把js调用oc的参数 封装成message对象 并把回调保存起来 function _doSend(message, responseCallback) { 
      if (responseCallback) { 
      var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); responseCallbacks[callbackId] = responseCallback; message['callbackId'] = callbackId; } sendMessageQueue.push(message); messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; } 

到这又开始触发到oc webview的代理回调里去了,即这块代码:

if ([_base isWebViewJavascriptBridgeURL:url]) { 
      if ([_base isBridgeLoadedURL:url]) { 
      [_base injectJavascriptFile]; } else if ([_base isQueueMessageURL:url]) { 
      //这次是走的这, 去调用js WebViewJavascriptBridge._fetchQueue(); // 取到刚刚push到sendMessageQueue 里的json NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; //处理js传过来的参数 如果有 callbackId 就说明js调oc的时候 oc是有回调的 [_base flushMessageQueue:messageQueueString]; } else { 
      [_base logUnkownMessage:url]; } return NO; } 

至此整个调用流程就走通了 O(∩_∩)O哈哈~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222003.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午4:47
下一篇 2026年3月17日 下午4:47


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号