美文网首页
iOS通过JavaScriptCore与JS交互

iOS通过JavaScriptCore与JS交互

作者: 来宝 | 来源:发表于2016-05-10 02:46 被阅读714次

    项目中需要用到与H5端的JS交互,总结一下用法:
    ios的 js 交互分为两块:
    一、OC调用JS
    这一块实现起来比较简单,一句代码搞定:

    -(void)webViewDidFinishLoad:(UIWebView *)webView
    {
    //首先创建JSContext对象、获取当前JS运行环境
        JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
     //无参的情况
        NSString *js1 = @"appMethod1()";
        [context evaluateScript:js1];
    //只有一个参数的情况
       NSString *js2 = @"appMethod2('参数')"; 
       [context evaluateScript:js2];
    //多个参数的情况
       NSString *js = [NSString stringWithFormat:@"appMethod3('%@','%@')",参数A,参数B];
       [context evaluateScript:js3];
    
    //注:[webView stringByEvaluatingJavaScriptFromString:js]
    与 [context evaluateScript:js]的功能的一样的;
    }
    
    
    后来项目中用到OC调用JS方法并传参的时候,发现上面的方法并不起作用,原因至今未找到,后来又找到了下面的方法可行:
    -(void)webViewDidFinishLoad:(UIWebView *)webView{
    
    //首先创建JSContext对象、获取当前JS运行环境
     JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
     JSValue *value = context[@"uploadPortrait"];
     [value callWithArguments:@[self.base64Image,self.imageName]];//两个参数
     [value callWithArguments:@[nil]];//无参的情况
    }
    

    注:OC调用JS的代码不一定写在webViewDidFinishLoad里面,可根据需要,写在所需的位置

    二、JS调用OC

    第一种情况: js端直接调用方法(block)

    //其中test1就是js的方法名称,赋给是一个block 里面是iOS代码
        //此方法最终将打印出所有接收到的参数,js参数是不固定的 我们测试一下就知道
    -(void)webViewDidFinishLoad:(UIWebView *)webView{
    //首先创建JSContext对象、获取当前JS运行环境
        JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    //将我们的context对象与js方法建立桥接联系,
        context[@"test1"] = ^() {
            NSArray *arguments = [JSContext currentArguments];
            for (id obj in arguments) {
                NSLog(@"%@",obj);
            }
          };
      }
        //首先准备一下js代码,来调用js的函数test1 然后执行
        NSString *jsFunctStr=@"test1('参数1')";
        [context evaluateScript:jsFunctStr];
    }
    

    第二种情况:JS端通过对象调用(常用方法)
    1、说到对象调方法我们首先肯定得有个对象,所以我们首先需要在OC端创建一个js交互类,并声明和实现相应的交互方法,
    2、需要在这个自定义交互类里面导入JavaScriptCore框架
    3、声明一个遵从于JSExport协议的协议(有点绕,看图),在这个协议里声明我们的交互方法(需要与JS端商定好方法名)

    JSObjectUtil.h文件

    #import <Foundation/Foundation.h>
    #import <JavaScriptCore/JavaScriptCore.h> //引入头文件
    #import "JXPayViewVC.h"//支付
    
    #pragma mark - 声明JS交互的协议,遵从于JSExport协议
    //JSObjectDelegate为协议名
    @protocol JSObjectDelegate <JSExport>
    
    #pragma mark - JS调用OC的方法,此方法名与网页端沟通 必须名字相同
     //payOrder...这个方法没有,这个方法的作用是当js端的方法有两个或两个以上参数时,
    //我们需要让- (void)payOrder:(NSString*)str appID:(NSString*)appID这个方法代替 “payForApp”这个方法,因为oc端的方法名必须和js端的保持一致,不然就不会被调用,如下:
     JSExportAs(payForApp, - (void)payOrder:(NSString*)str appID:(NSString*)appID); 
    //此外,也可以自己拆分方法名,如:payForApp---->pay:xxx For:xxx App:xxx
    
    //调用支付宝、微信支付(下面为OC端方法)
    -(void)pay:(NSString *)params For:(NSString *)backParams App:(NSString *)payOrg;
    @end
    
    #pragma mark - 让我们创建的类实现上边的协议
    @interface JSObjectUtil : NSObject<JSObjectDelegate>
    //这里的payMoney可以用来直接调用JXPayViewVC类里面的任何方法
    @property(nonatomic,strong)JXPayViewVC *payMoney;
    
    @end
    

    JSObjectUtil.m文件

    #import "JSObjectUtil.h"
    @implementation JSObjectUtil
    //支付
    //1、payForApp()是OC端的方法名,含有三个参数,因此需要对payForApp进行拆分加参数
    //2、是通过OC端调用JS端的appMethod方法,同时JS端在appMethod方法里面套入需要调用OC端的方法名进行调用
    //3、OC 端可以在被JS端调用的方法里面,让遵从交互协议类的对象调用此类里面的方法
    -(void)pay:(NSString *)params For:(NSString *)payID App:(NSString *)payOrg
    {
        NSLog(@"JS调用了OC的payForApp方法");
       //self.payMoney对象调用JXPayViewVC类的方法
        [self.payMoney sendPay:params payID:payID payOrder:payOrg];
    }
    @end
    
    

    加载webView页面类的.m文件

    -(void)webViewDidFinishLoad:(UIWebView *)webView{
        //加载JS交互
        [self loadJSObject:webView];
    }
    -(JSContext *)loadJSObject:(UIWebView *)webView{
        //1、首先创建JSContext对象、获取当前JS运行环境
        JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
        //2、创建模型来调用方法
        JSObjectUtil *jsUtil = [JSObjectUtil new];
        jsUtil.payMoney = self;//让我们的交互类遵从协议
    
        //3、注入JS对象,其中"AppFunLoader"是JS的对象名,需要与JS端商定好名称,用它来调用下面的pay的appMethod方法
        context[@"AppFunLoader"] = jsUtil;
    
       //4、开始调用JS端的appMethod方法
        NSString *pay = @"appMethod()";
        [context evaluateScript:pay];
        
        return context;
    }
    
    

    相关文章

      网友评论

          本文标题:iOS通过JavaScriptCore与JS交互

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