OC与JS数据交互

作者: xshenpan | 来源:发表于2016-05-18 20:26 被阅读3618次
    • iOS7之后有了JavaScriptCore框架使得OC与JS的交互变得简单了起来.
    • 在学习webView的时候,发现OC与JS做交互时用的是截取webView的响应来获得想要的数据(不得不佩服,办法很高端)。感觉这种办法太蛋疼了,于是抱着试一试的心态到官方文档搜索JavaScript关键字,于是出来了下面一段
    QQ20160518-0.png
    • 看到了这句话很是兴奋啊!于是又往下继续找
    QQ20160518-1.png
    • 竟然还有例子耶,来试试吧!

      • 结果可想而知,并没有什么卵用webView根本没有windowScriptObject方法
      • 回头一看还有一句 any WebKit-based OS X application原来是OS X才能用
    • 然后继续上网找资料啊

      • 找到了这样一个博客
        http://blog.csdn.net/lwjok2007/article/details/47058101/
        讲了在OC执行JS
        http://blog.csdn.net/lwjok2007/article/details/47058795
        讲了在JS调用OC方法
        里面写了怎样使用JavaScriptCore框架让OC和JS的交互,我就不搬运了。里面的关于导入框架,介绍JavaScriptCore的使用等等一些东西写的都比较清楚了。
        然后我把里面的东西拿出来验证了一下,也把JSExport用法写的更详细了一点,block的方式没有使用。上面的文章里面没有讲到 JSExportAs宏,所以JS函数名称比较恶心
    • JS与OC的数据类型对应如下<JSValue.h>有描述

    QQ20160518-2.png
    • 要说的都在注释里了,OC代码如下(HTML在最下面):
    
    #import "ViewController.h"
    #import <JavaScriptCore/JavaScriptCore.h>
    
    //自己定义一个协议遵守JSExport协议,然后想要导出这些方法的类再遵守这个协议就可以了
    @protocol ObjcExportMethod <JSExport>
    
    //JSExportAs宏将 "- showNumber1:andNumber2:"方法名 转换为showNumber(param1, param2)
    //如果不使用JSExportAs转换,那么在js中调用的函数名为showNumber1AndNumber2(param1, param2);
    //注意:JSExportAs宏只适合转换有参的方法,不能转换无参的方法
    JSExportAs(showNumber,
    - (void)showNumber1:(NSNumber *)n1 andNumber2:(NSNumber *)n2
    );
    
    JSExportAs(returnSum,
    - (NSNumber *)returnSumWithNum1:(NSNumber *)n1 andNum2:(NSNumber *)n2
    );
    
    JSExportAs(dictTest,
    - (void)dictTest:(NSDictionary *)dict
    );
    
    JSExportAs(arrayTest,
    - (void)arrayTest:(NSArray *)array
    );
    
    - (void)show;
    - (NSString *)returnString;
    - (NSDictionary *)returnDict;
    - (NSArray *)returnArray;
    @end
    
    /**
      * UIViewController
      */
    @interface ViewController () <UIWebViewDelegate, ObjcExportMethod>
    @property (weak, nonatomic) IBOutlet UIWebView *webView;
    @end
    
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //加载本地测试网页
        [self.webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"]]];
    
    }
    
    #pragma mark - <ObjcExportMethod>
    
    /**
     *  无参导出方法
     */
    - (void)show
    {
        NSLog(@"%s", __func__);
    }
    /**
     *  返回一个OC字符串到JavaScript
     */
    - (NSString *)returnString
    {
        return @"从OC返回成功";
    }
    /**
     *  返回一个OC数组到JavaScript
     */
    - (NSArray *)returnArray
    {
        return @[@(1), @"hello"];
    }
    /**
     *  返回一个OC字典到JavaScript
     */
    - (NSDictionary *)returnDict
    {
        return @{
                 @"name" : @"jack",
                 @"date" : @[@(1), @"hello"]
                 };
    }
    /**
     *  从JavaScript接收两个NSNumber参数,计算他们的和并返回计算结果到JS
     */
    - (NSNumber *)returnSumWithNum1:(NSNumber *)n1 andNum2:(NSNumber *)n2
    {
        return @(n1.intValue + n2.intValue);
    }
    /**
     *  从JavaScript接收两个NSNumber类型的值,打印出来
     */
    - (void)showNumber1:(NSNumber *)n1 andNumber2:(NSNumber *)n2
    {
        NSLog(@"number1 = %@, number2 = %@", n1, n2);
    }
    /**
     *  从JavaScript接收一个字典
     */
    - (void)dictTest:(NSDictionary *)dict
    {
        NSLog(@"%@",dict);
    }
    /**
     *  从JavaScript接收一个数组
     */
    - (void)arrayTest:(NSArray *)array
    {
        NSLog(@"%@", array);
    }
    
    
    #pragma mark - <UIWebViewDelegate>
    
    /**
     *  完成加载
     */
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        //得到当前页面的JSContext,如果不在这里获得当前网页的context可能有问题
        JSContext *js = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        //设置 js 代码中的method对象为控制器
        js[@"method"] = self;
        
        //在OC中执行js并取得js返回的数据
        //方式1 使用JSContext的对象方法执行JS脚本
        NSString *jsScript = @"document.title";     //获取网页标题
        //evaluateScript方法返回的是JSValue类型的对象,需要将类型转换为OC对象
        NSString *title = [js evaluateScript:jsScript].toString;
        self.navigationItem.title = title;
        NSLog(@"evaluateScript --->  %@",title);
    
        //方式2 使用webView的对象方法执行js,该方法返回的数据类型始终是NSString,不管JS实际传递过来的是什么类型,
        //如JS传递过来的是10 那么该方法的返回值任然是字符串
        title = [webView stringByEvaluatingJavaScriptFromString:jsScript];
        NSLog(@"stringByEvaluating ---> %@", title);
    }
    
    @end
    
    
    • 测试用HTML代码如下:
    <html>
        <head>
        <meta charset="UTF-8"/>
        <title>测试网页</title>
        <script>
            //遍历数组
            function ArrayFun(array)
            {
                for(var i = 0; i < array.length; i++)
                {
                    alert(array[i]);
                }
            }
            // 遍历字典
            function DictionaryFun(dict)
            {
                for (var key in dict)
                {
                    alert(key + " : " + dict[key]);
                }
            }
        </script>
        </head>
        
    
        <body>
            <h5 style="color:blue" onclick="method.show();">调用OC无参无返回值方法</h5>
            <h5 style="color:blue" onclick="alert(method.returnString());">从OC返回字符串</h5>
            <h5 style="color:blue" onclick="method.showNumber(1,2);">传递2个整数到OC</h5>
            <h5 style="color:blue" onclick="alert(method.returnSum(10,20));">传递2个整数到OC,得到他们的和</h5>
            <h5 style="color:blue" onclick="method.arrayTest([1,2,'hello oc', {'name':'jack'}]);">传递数组到OC</h5>
            <h5 style="color:blue" onclick="method.dictTest({'name':'jack', 'data':[1, 'hello', {'age' : 10}]});">传递字典到OC</h5>
            <h5 style="color:blue" onclick="DictionaryFun(method.returnDict());">从OC返回字典</h5>
            <h5 style="color:blue" onclick="ArrayFun(method.returnArray());">从OC返回数组</h5>
        </body>
        
    </html>
    

    相关文章

      网友评论

      • 萝卜酱紫:问下 JS调OC
        context[@"getMoney"] = ^(){

        };
        这个方法我要给 js传个值怎么写?

        xshenpan:@萝卜酱紫 嗯嗯,好的
        萝卜酱紫:@xshenpan 解决了 我是执行实际的问题控制器view加载web 就执行这个方法 也不是 web didfinish 才执行
        xshenpan:@萝卜酱紫 不好意思啊,现在好久没用了:joy:,都忘得差不多了。
        可不可以在block中调与js交互的方法传值?
      • 择择lee:很棒
        xshenpan:@择择lee 谢谢
      • 99e37a598093:很好唉

      本文标题:OC与JS数据交互

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