OC和JS的交互---JavaScriptCore

JavaScriptCore的简单介绍

JavaScriptCore是iOS7提供的原生框架,可以让Objective-C和JavaScript提供简单直接的交互。

JavaScriptCore的使用

导入JavaScriptCore.framework

在需要使用的类中引入头文件

#import <JavaScriptCore/JavaScriptCore.h>

点开头文件,我们可以看到

#import "JSContext.h"
#import "JSValue.h"
#import "JSManagedValue.h"
#import "JSVirtualMachine.h"
#import "JSExport.h"

这些都是框架的时候会使用到的东西。

通过OC执行JS方法或调取JS属性

    //通过OC执行js方法或调取js属性。
    JSContext *context = [[JSContext alloc]init];
    [context evaluateScript:@"var arr = [1, 2, 'This is js string'];var sum = function(a, b) { return a+b;}"];
    //访问js中定义的数组arr
    JSValue *jsArr = context[@"arr"];
    NSArray *ocArr = jsArr.toArray;
    NSLog(@"%@",ocArr);
    
    //执行js中定义的方法,传入参数并得到结果
    JSValue *jsSum = context[@"sum"];
    JSValue *jsSumResult = [jsSum callWithArguments:@[@2,@3]];
    NSInteger sumResult = jsSumResult.toInt32;
    NSLog(@"%d",(int)sumResult);

JSContext对象:

  它是JS的运行环境,它有一个方法-evaluateScript,这个方法可以运行一段js代码。而且,js中的所有变量方法都会保存在JSContext中,通过操作JSContext对象,可以实现调用js的方法和存取js的对象。

JSValue对象:

  它对应着JSContext中的所有方法和属性,它也是OC和JS相互访问和修改的中间体,所有OC 和 javaScript的跨语言操作都要通过JSValue一些方法进行。

NSNumber *jsarr0 = jsArr[0].toNumber;
jsArr[1] = @3;

  通过JSValue对象的 callWithArguments:方法来直接调取 js 的 function。js function的多参数,在OC中,由NSArray组装而成。

    //执行js中定义的方法,传入参数并得到结果
    JSValue *jsSum = context[@"sum"];
    JSValue *jsSumResult = [jsSum callWithArguments:@[@2,@3]];
//    JSValue *jsSumResult = [jsSum callWithArguments:[NSArray arrayWithObjects:@2, @3, nil]];
    //jsSumResult = 5;

通过JS执行OC方法,或者调用OC属性

我们可以使用Block来调用方法

-(NSInteger) sumWithA:(NSInteger)a WithB:(NSInteger)b WithC:(NSInteger)c{
    return a+b+c;
}

-(void)test{
    JSContext *context = [[JSContext alloc]init];
    context[@"sumNums"] = ^(NSInteger a,NSInteger b,NSInteger c){
        return [self sumWithA:a WithB:b WithC:c];
    };
    
    JSValue *sum = [context evaluateScript:@"sumNums(7, 56, 22)"];
    NSLog(@"%@",sum);
}

上述代码中,sumWithA:WithB:WithC 是我们定义的OC的方法,在JS调用OC方法时,首先声明一个JSContext对象,然后对sumNums赋值一个Block,在Block中,我们调用OC定义的方法sumWithA:WithB:WithC。我们使用evaluateScript来执行一段JS代码,尝试调用OC方法,最后输出结果。

1. 不论在任何情况下,不要在Block中直接使用外面的JSValue对象, 而应该把JSValue当做参数来传进Block中。
2. 不论在任何情况下,不要在Block中直接使用外面的JSContext对象, 而应该使用 [JSContext currentContext]获取。