美文网首页iOS Developer
JavaScriptCore的基本用法(一)

JavaScriptCore的基本用法(一)

作者: 七里小晴天 | 来源:发表于2016-06-12 11:07 被阅读376次

    刚来新公司的第一天就要加班,一脸的苦逼。还好这是被安排研究一下OC和js的交互,对于这个apple新推出的库还没接触过,所以就在这里做一个简单的记录。

    JavaScriptCore简介

    iOS 7中加入了JavaScriptCore框架。该框架让Objective-C和JavaScript代码直接的交互变得更加的简单方便。而且使得js可以脱离webview与oc交互。
    在项目中引入JavaScriptCore后,链到头文件中,除了大段的Copyright注释可以看到里面只要引入了5个文件,每个文件里都定义跟文件名对应的类:


    Paste_Image.png
    JSContext和JSValue

    <a style = "color:red; font: bold;">JSContext</a>

    //JSVirtualMachine为JavaScript的运行提供了底层资源,JSContext就为其提供着运行环境,该方法用来执行一段
    //JS代码,并且如果其中有方法、变量等信息都会被存储在其中以便在需要的时候使用。
    - (JSValue *)evaluateScript:(NSString *)script
    //JSContext的创建都是基于JSVirtualMachine,如果是使用- (id)init;
    //进行初始化,那么在其内部会自动创建一个新的JSVirtualMachine
    //对象然后调用前边的初始化方法
    - (id)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;
    

    <a style = "color:red; font: bold;">JSValue</a>
    则可以说是JavaScript和Object-C之间互换的桥梁,它提供了多种方法可以方便地把JavaScript数据类型转换成Objective-C,或者是转换过去。其一一对应方式可见下表:


    4ABEE7D7-1DCB-4A21-A708-4CEA36782D6C.png

    基本类型的转换

    JSContext *context = [[JSContext alloc] init];
    JSValue *jsVal = [context evaluateScript:@"2+7"];
    int iVal = [jsVal toInt32];
    NSLog(@"JSValue: %@, int: %d", jsVal, iVal);
    //输出9
    

    还可以存一个Js变量在JSContext中,然后通过下标取出来。对于数组或者对象类型,JSValue也可以通过下表直接取值和赋值.

    [context evaluateScript:@"var arr = [21, 7 ,'leo']"];
    JSValue *value = context[@"arr"];
    value[1] = @"blog";
    value[7] = @7;
    NSArray *array = [value toArray];
    打印数组看一下
    Printing description of array:
    <__NSArrayM 0x7fabc144ea40>(
    21,
    blog,
    leo,
    <null>,
    <null>,
    <null>,
    <null>,
    7
    

    代码成功把数据从OC�赋值到了Js数组上,而且jsValue遵循js数组的特性,无下标越位,自动延展数组大小

    方法的转换(js调用oc的第一种方法)

    各种数据类型可以转换,Objective-C的Block也可以传入JSContext中当做JavaScript的方法使用。

      context[@"add"] = ^(NSInteger a, NSInteger b){
           //获取该方法的对象
            JSValue *v = [JSContext currentThis];
            //获取当前的参数
            NSArray *args = [JSContext currentArguments];
            NSLog(@"当前对象:%@",v);
            NSLog(@"当前参数:%@",args);
            NSLog(@"和是%ld",a + b);
        };
        [context evaluateScript:@"add(1,2)"];
        
        输出如下:
        当前对象:GlobalObject
        当前参数:(
        1,
        2)
        和是3
    

    上边的例子中对于"this"输出的内容是GlobalObject,这也是JSContext对象方法- (JSValue *)globalObject;所返回的内容。因为我们知道在JavaScript里,所有全局变量和方法其实都是一个全局变量的属性,在浏览器中是window,在JavaScriptCore是什么就不得而知了。

    Block可以传入JSContext作方法,但是JSValue没有toBlock方法来把JavaScript方法变成Block在Objetive-C中使用。毕竟Block的参数个数和类型已经返回类型都是固定的。虽然不能把方法提取出来,但是JSValue提供了- (JSValue *)callWithArguments:(NSArray *)arguments;方法可以反过来将参数传进去来调用方法。

    JSContext *context = [[JSContext alloc]init];
        NSString *js = @"function add(a,b){return a+ b;}";
        [context evaluateScript:js];
        JSValue *value = [context[@"add"] callWithArguments:@[@3,@4]];
        NSLog(@"%@",value);
        
        输出如下:
        7
        
    

    JSValue还提供

    - (JSValue *)invokeMethod:(NSString *)method withArguments:(NSArray *)arguments;
    

    让我们可以直接简单地调用对象上的方法。只是如果定义的方法是全局函数,那么很显然应该在JSContext的globalObject对象上调用该方法;如果是某JavaScript对象上的方法,就应该用相应的JSValue对象调用。

    相关文章

      网友评论

        本文标题:JavaScriptCore的基本用法(一)

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