Author: geneblue
Blog: https://geneblue.github.io/
介绍
apple 从 iOS7.0 开始增加了 JavaScriptCore 框架。该框架提供了在
Swift,Objective-C 和 C 这些 native code 中执行 javascript
脚本的能力,当然,也支持将 native object 插入到 js 的执行环境中。
demo
JavaScriptCore 框架的使用非常简单,看以下 demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
{ //创建虚拟机 JSVirtualMachine *vm = [[JSVirtualMachine alloc] init]; //创建上下文 JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm];
//执行JavaScript代码并获取返回值 JSValue *value = [context evaluateScript:@"1+2*3"];
//转换成OC数据并打印 NSLog(@"value = %d", [value toInt32]); }
|
三行代码就建立了一个 js 执行环境并执行一段小脚本。JSVirtualMachine
会为我们建立一个独立的 vm 环境,JSContext 会建立 js 执行的上下文,一个
vm 里可以创建多个 context 环境,而且这些 context 中的 JSValue
可以互相使用。内存管理由 vm 负责,完全不用我们操心的。
关键类介绍
#import <JavaScriptCore/JavaScriptCore.h>
头文件,主要引入以下关键类
1 2 3 4 5
| #import "JSContext.h" #import "JSValue.h" #import "JSManagedValue.h" #import "JSVirtualMachine.h" #import "JSExport.h"
|
JSVirtualMachine JSContext
建立 vm 环境,建立 context 上下文
JSValue
JSValue 用于在 native 代码和 js 之间传递数据,JSValue 与 context
是一一对应的,可以通过 JSValue 直接拿到对应的 context;当然,JSValue
也提供了很多方法,让 native 和 js 的数据类型进行转换。native 与 js
复杂的数据类型转换,见参考。
JSManagedValue
将JSValue转换为JSManagedValue,则运行时两侧都可以正常访问对象,避免一端释放一端仍然持有的状态。
JSExport
导出OC的函数与属性供JavaScript使用,继承了这个协议的协议中定义的方法,就可以直接在JSContext中被使用
OC 与 JS 的互相交互
OC 调用 JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| JSVirtualMachine *jsvm = [JSVirtualMachine new];
JSContext *context = [[JSContext alloc] initWithVirtualMachine:jsvm];
JSValue *value = [context evaluateScript:@"1+2*3"]; NSLog(@"value = %d", [value toInt32]); JSValue *value2 = [context evaluateScript:@"function hi(){ return 'hi' }; hi()"]; NSLog(@"value = %@", [value2 toString]);
NSString *path = [[NSBundle mainBundle] pathForResource:@"jscalloc" ofType:@"js"]; NSString *html = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; JSValue *value3 = [context evaluateScript:html]; NSLog(@"value = %@", [value3 toString]);
[context evaluateScript:@"var hello = function(){ return 'hello' }"]; JSValue *value4 = [context evaluateScript:@"hello()"]; NSLog(@"value = %@", [value4 toString]);
JSValue *jsFunc = [context evaluateScript:@"(function(){return 'hello objc'})"]; JSValue *value5 = [jsFunc callWithArguments:nil]; NSLog(@"value = %@", [value5 toString]);
|
JS 调用 OC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| JSVirtualMachine *jsvm = [JSVirtualMachine new];
JSContext *context = [[JSContext alloc] initWithVirtualMachine:jsvm];
context[@"log"] = ^(NSString *msg){ NSLog(@"OCMethod: log called from js: %@", msg); return @"this is log1"; };
context[@"log2"] = ^() { NSArray *args = [JSContext currentArguments]; for (id obj in args) { NSLog(@"OCMethod2: log called from js: %@", obj); } };
JSValue *value6 = [context evaluateScript:@"log('this is method log')"]; NSLog(@"value = %@", [value6 toString]);
[context evaluateScript:@"log('this is method log2')"];
NSLog(@"this is te");
|
参考