zoukankan      html  css  js  c++  java
  • OC和JS交互的三种方法

      看简书上说一共有六种OC和JS交互的方法,但是前三种原理都一致,都是通过检测、拦截Url地址实现互相调用的。剩下的react native等第三方框架原理不一样,也没有去研究,下边记录我使用的三种方法(原理都是拦截Url地址)。

      (一)、使用系统自带JavaScriptCore库进行交互,支持iOS7以后系统。(备注:我这个项目在交互MBProgress的时候控制隐藏,js代码会发生奔溃,安卓是好的,原因始终找不到)

    oc调用js方法

    [homeWebView stringByEvaluatingJavaScriptFromString:jsFunction];

    -------------------------------------------------------------------

    js调用oc方法导入

      1、JavaScriptCore库

      #import <JavaScriptCore/JavaScriptCore.h>

      2、获得上下文

    - (void)webViewDidFinishLoad:(UIWebView *)webView{

        //降低webview带来的内存泄露

        [[NSUserDefaultsstandardUserDefaults] setInteger:0forKey:@"WebKitCacheModelPreferenceKey"];

        //----------------------JS回掉方法----------------------------------------

      JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    //没有返回值的写法

        context[@"showProgressDialogPhone"] = ^() { // 显示

            [self showProgressDialog];

        };

      // 有返回值的写法,

      context[@"getTabInfoIOS"] = [self getTabInfoIOS];//获得权限

    }

    3、js端绑定方法oc方法,绑定的这个方法名称必须要和oc里注册的方法名称保持一致

       function showProgressDialog(){

          showProgressDialogPhone();

        }

    (二)、实现了JSExport协议的协议,这样调用到vc里的方法

    1、声明协议,实现协议方法

    在.h文件中声明

    @protocol TestJSObjectProtocol <JSExport>

    -(void)closeProgressDialog;

    @end

    .m文件中实现协议方法

    @interface ViewController ()<TestJSObjectProtocol>

    @end

    1、同上先获得上下文,oc这里绑定方法、实现closeProgressDialog方法

            ViewController *viewCtlOBJ = [ViewController new];

            context[@"viewCtlOBJ"] = viewCtlOBJ;

            NSString *jsStr1=[NSString stringWithFormat:@"viewCtlOBJ.closeProgressDialog()"];

            [context evaluateScript:jsStr1];

    2、js这边调用oc方法

    function closeProgressDialog(){

     viewCtlOBJ.closeProgressDialog();

    }

    (三)、使用WebViewJavascriptBridge进行oc和js的交互

    备注:兼容iOS7以下版本,我最终使用的这个方法,解决掉js代码崩溃的问题。这个类库是异步执行的,优点:调用oc和js代码优雅,传值和回调方便

    1、先导入WebViewJavascriptBridge包,可参考上一篇文章导入。

      #import "WebViewJavascriptBridge.h"

      @propertyWebViewJavascriptBridge* bridge;

      2、OC原生注册方法,实现方法

       [WebViewJavascriptBridgeenableLogging];

        _bridge = [WebViewJavascriptBridgebridgeForWebView:homeWebView];

        [_bridgesetWebViewDelegate:self];

        /***

         /js调用oc

         /@param registerHandler 要注册的事件名称(这里我们为showProgressDialogPhone)

         /@param handel 回调block函数 当后台触发这个事件的时候会执行block里面的代码

         ***/

        [_bridgeregisterHandler:@"showProgressDialogPhone"handler:^(id data, WVJBResponseCallback responseCallback) {

            NSLog(@"显示加载");

            [self showProgressDialog];

            responseCallback(@"Response 显示加载");

        }];

      3、js端调用注册的方法

      //固定写法

    function setupWebViewJavascriptBridge(callback) {

        if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }

        if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }

        window.WVJBCallbacks = [callback];

        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)

    }

        setupWebViewJavascriptBridge(function(bridge) {

                                     bridge.callHandler('showProgressDialogPhone', function(response) {

                                                      alert(response);

                                                        })

                                     });

     -----------------------------------------------------------------------------------------

       //oc调用js代码

         bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {

       log('ObjC called testJavascriptHandler with', data)

           var responseData = { 'Javascript Says':'Right back atcha!' }

                                                      responseCallback(responseData)

                                                      })

        //需要传参数,不需要从后台返回执行结果

        /***

         @param callHandler 商定的事件名称,用来调用网页里面相应的事件实现

         @param data id类型,相当于我们函数中的参数,向网页传递函数执行需要的参数

         ***/

    //    [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];

    --------------------------------------------------------------------------------------

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    C# 6.0 新特征 Demo
    SmartGit 试用过期
    .net版Git Server --- bonobo
    线程操作若干(复习)
    异步的两种写法: async 与 BeginInvoke
    winform 防止主界面卡死
    wcf 出现 IsContentTypeSupported 错误
    NodeJs 实时压缩 项目js文件
    Excel 公式(细节若干)
    itextSharp 对pdf的每个页面添加footer/header
  • 原文地址:https://www.cnblogs.com/shizhiliblog/p/7652098.html
Copyright © 2011-2022 走看看