JavaScriptCore的基本用法(一)

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

JavaScriptCore简介

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


Paste_Image.png
JSContext和JSValue

JSContext

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

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


JavaScriptCore的基本用法(一)_第1张图片
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,
,
,
,
,
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的基本用法(一))