zoukankan      html  css  js  c++  java
  • WebViewJavaScriptBridge的原理解析

    理解WebViewJavaScriptBridge原理

    前提条件都是需要bridge在OC实例化,然后二者的互调才可以进行下去

    _bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
    

    实例化的原理是:JSBridge里面有UIWebview和JSBridgeBase的实例,然后分别成为二者的代理,负责协调双方的工作

    第一部分:js调用OC方法:

    由OC注册,JS主动触发(调用callhandler方法)

    1.执行前提条件

    2.OC在注册(registerHandler)的时候,OC会注册一个回调函数

    [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback)
    

    ,该回调函数包括一个注册事件和一个回调方法,JSB中的base实例会把该注册事件放进到base的一个消息池子(负责接受多个OC注册事件)中,方便后续处理

    3.网页加载出来后整个oc的执行流程

    相当于JS的注册绑定方法--->当UIWebview把该网页加载出来的时候,在该html文件中会通过JS的iframe元素执行JS和OC端的绑定。

    该方法是由于webview的delegate设置为了JSB,所以会在JSB中触发其代理方法:shouldStartLoadWithRequest,然后在该方法中进行如下操作:

    根据url(此时的url是由上述的iframe元素带进来的,类似:wvjbscheme://BRIDGE_LOADED ) ,来决定此时是走registerHandler 还是 callHandler方法,此时是register方法,那么则执行JSBridgeBase的injectJavascriptFile方法(正如函数名一样,此时执行在工程里面放置的JS文件(在我们的工程里面由于要兼容JSBridge的历史版本,所以这里是在webViewDidFinishLoad里面直接调用injectJavascriptFile方法)),这个文件的主要作用就是向OC发消息来定义一些常量,注册一些实例,定义一些回调方法,方便在OC的逻辑中进行处理和跟踪,文件执行完毕后,接下来就会查找在base中时候有OC要发送给JS的回调信息,没有则执行结束(这里显然没有)

    4.oc和js相互绑定过后,此时由JS触发OC函数

    点击JS上的button会触发callHandler,会触发代理shouldStartLoadWithRequest:
    此时由于经由上述的JS文件执行的时候会执行一个叫做window.WebViewJavascriptBridge的注册

    window.WebViewJavascriptBridge = {
    		registerHandler: registerHandler,
    		callHandler: callHandler,
    		disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
    		_fetchQueue: _fetchQueue,
    		_handleMessageFromObjC: _handleMessageFromObjC
    	};
    
    

    由于js主动触发了callHandler,url所以变成了
    wvjbscheme://WVJB_QUEUE_MESSAGE ,所以此时会走一个执行js函数的方法(猜测是通过上述js文件的作用从而能够解析出JS传递过来的信息)来从网页上获得网页的传递过来的信息!

    {
      "callbackId" : "cb_2_1468844907930",
      "handlerName" : "testObjcCallback",
      "data" : {
        "foo" : "bar"
      }
    }
    

    然后进入base的flushMessageQueue:函数,在里面通过解析该dict,从而获得注册事件名handlerName,然后获得该事件的回调,并调用那个事件的回调block

    handler(message[@"data"], responseCallback);
    

    至此,整个JS回调OC过程完成,达到了JS给OC发送数据的目的,同时如果OC想要给JS发送消息,只需把信息放进responseCallback就会回调给JS(方法就是第二部分的内容),以达到互相通信的目的



    第二部分:OC调用js方法:

    由js注册,OC主动触发(调用callhandler方法)

    1.执行前提条件

    2.网页加载出来后整个oc的执行流程

    相当于JS的注册方法--->当UIWebview把该网页加载出来的时候,在该html文件中会通过JS的iframe元素执行JS和OC端的绑定。

    该方法的由于webview的delegate设置为了JSb,所以会在JSB中触发其代理方法:shouldStartLoadWithRequest,然后在该方法中进行如下操作:

    根据url(此时的url是由上述的iframe元素带进来的,类似:wvjbscheme://BRIDGE_LOADED ) ,来决定此时是走registerHandler 还是 callHandler方法,此时是register方法,那么则执行JSBridgeBase的injectJavascriptFile方法(正如函数名一样,此时执行在工程里面放置的JS文件),这个文件的主要作用就是向OC发消息来定义一些常量,注册一些实例,定义一些回调方法,方便在OC的逻辑中进行处理和跟踪,
    其中会执行一个叫做window.WebViewJavascriptBridge的注册

    window.WebViewJavascriptBridge = {
    		registerHandler: registerHandler,
    		callHandler: callHandler,
    		disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
    		_fetchQueue: _fetchQueue,
    		_handleMessageFromObjC: _handleMessageFromObjC
    	};
    
    

    由于js函数中一进来便主动触发了registerHandler,所以url变成了
    wvjbscheme://WVJB_QUEUE_MESSAGE
    文件执行完毕后,会在JSB中执行

    else if ([_base isQueueMessageURL:url]) {
    NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
                [_base flushMessageQueue:messageQueueString];
                }
    

    恰好此时url 满足情况,则进入消息分发流程,但是由于此时messageQueueString什么也没有,所以直接跳出

    3.OC和js相互绑定过后,此时由OC函数触发JS

    点击OC的button,触发OC函数

    [_bridge callHandler:@"testJavascriptHandler" data:@{@"name": @"wayne"} responseCallback:^(id responseData)
    

    调用Base的

    - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName
    

    使用dictionary进行消息拼接,形如:

    {
        callbackId = "objc_cb_1";//定义OC的回调id
        data =     {
            name = wayne;
        };//OC传递给JS的数据
        handlerName = testJavascriptHandler;//为了区分是哪一个注册事件,以便后续的消息分发
    }
    

    封装完成过后,会调用[self _dispatchMessage:message]来进行消息分发,消息分发是在主线程里面执行的,消息的内容经过再次封装过后形似:

    WebViewJavascriptBridge._handleMessageFromObjC('{"callbackId":"objc_cb_1","data":{"name":"wayne"},"handlerName":"testJavascriptHandler"}');
    

    WebViewJavascriptBridge._handleMessageFromObjC-->查看JS文件可知,这个文件是给JS使用的,会执行_handleMessageFromObjC的方法把消息分发给JS中的registerHandler中的方法体,OC回调过程结束!!

    4.JS传递数据给OC

    但是此时在执行JS中的代码的时候发现有回调block,则会执行改block

    然后会再次执行UIWebview的代理方法:shouldStartLoadWithRequest函数,此时url已经是
    wvjbscheme://WVJB_QUEUE_MESSAGE
    文件执行完毕后,会在JSB中执行

    else if ([_base isQueueMessageURL:url]) {
    		NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
            [_base flushMessageQueue:messageQueueString];
          }
    

    messageQueueString由第一部分知识可知:是JS传递过来的数据:

    [{
    "handlerName":"testJavascriptHandler",
    "responseId":"objc_cb_1",
    "responseData":
    		{"Javascript Says":"Right back atcha!==>test"}
    }]
    

    执行flushMessageQueue函数:并在里面执行block函数体,获得JS传递过来的数据

    至此,互相传递数据过程完毕!

  • 相关阅读:
    IE8下,时间函数问题
    sublime有时候用快捷键时出现的是css的快捷键
    热词高亮并去重
    关于百分比的margin
    手机端后退功能
    CSS3小水滴代码
    关于Gmapping的学习2
    关于概率运动模型
    A*算法的学习
    经典ICP算法
  • 原文地址:https://www.cnblogs.com/WayneLiu/p/5738936.html
Copyright © 2011-2022 走看看