ios7之后,ios中加入了JavaScriptCore框架。该框架让Objective-C和JavaScript代码直接的交互变得更加的简单方便。
一、JSContext 与 JSValue
JSContext是OC与js交互的中间上下文,用于相互转化。
在iOS框架中,凡是带session或者context后缀的,这种类一般自己不干活,作用一般都是两个:1.管理其他类,帮助他们搭建沟通桥梁,好处就是解耦 2.负责帮助我们管理复杂环境下的内存
context与session不同之处是:session一般与硬件打交道,例如摄像头捕捉ARSession,网卡的调用NSURLSession等使用的都是session后缀。没有硬件参与,一般用context,如绘图上下文,自定义转场上下文等。
JSValue则可以说是JavaScript和Object-C值之间互换的桥梁,它提供了多种方法可以方便地把JavaScript数据类型转换成Objective-C,或者是转换过去。
二、OC 调用js代码
JSContext *context = [JSContext new];
JSValue *result = [context evaluateScript:@"1 + 2"];
NSLog(@"%.2f",[result toDouble]);
三、 OC调用JS 的函数
//先定义一句js上下文,带有sum函数
JSContext *context = [JSContext new];
NSString *js = @"function sum(a,b) {return a+b;}";
[context evaluateScript:js];
JSValue *sum = context[@"sum"];
JSValue *result = [sum callWithArguments:@[@1,@2]];
NSLog(@"%.2f",[result toDouble]);
四、在OC中js 中报错
如果js代码报错,项目中是无法体现的,所以要进行异常处理
JSContext *context = [JSContext new];
context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
NSLog(@"%@",exception);
};
[context evaluateScript:@"a.b = 123"];
五、block 与 js 进行互动
JSContext *context = [JSContext new];
//block 与 js 进行互动时, block里面不要调用外边oc的变量
context[@"sum"]=^(int a, int b) {
//想在这里拿到contextz
//JSContext *ctx = [JSContext currentContext];
return a + b;
};
JSValue *result = [context evaluateScript:@"sum(1,2)"];
NSLog(@"%.2f",[result toDouble]);
六、 给js中添加对象
创建Point3D类,利用协议
Point3D.h文件
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
@protocol Point3DExport <JSExport>
@property double x;
@property double y;
@property double z;
-(double)length;
@end
@interface Point3D : NSObject<Point3DExport>{
JSContext *context;
}
-(id)initWithContext:(JSContext *)ctx;
@end
Point3D.m文件
#import "Point3D.h"
@implementation Point3D
@synthesize z;
@synthesize y;
@synthesize x;
-(id)initWithContext:(JSContext *)ctx{
if (self =[super init]) {
context = ctx;
context[@"Point3D"] = [Point3D new];
}
return self;
}
-(double)length {
return sqrt(self.x * self.x + self.y * self.y + self.z * self.z);
}
@end
调用
JSContext *context = [JSContext new];
Point3D *point3D = [[Point3D alloc] initWithContext:context];
point3D.x = 1;
point3D.y = 2;
point3D.z = 3;
context[@"point3D"] = point3D;
NSString *script = @"point3D.x = 2;point3D.y = 2;point3D.length()";
JSValue *result = [context evaluateScript:script];
NSLog(@"%.2f",[result toDouble]);
当执行 context[@”point3D”] = point3D;时,相当于通过OC往js中添加point3D对象,但是js中并没有point3D class,只是把对象塞了过来。
七、OC 调用js 文件
创建test.js
var foo = function(a) {
return "Hello Oc,I'm foo in JS."+a;
};
function bar(a) {
return "Hello Oc,I'm bar in JS."+a;
};
foo(123);
bar(123);
console.log(foo(123));
此时console不能打印在xcode控制台
因此要创建Console类来重写打印方法
Console.h
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
@protocol ConsoleExport <JSExport>
- (void)log;
@end
@interface Console : NSObject <ConsoleExport>{
JSContext *context;
}
-(id)initWithContext:(JSContext *)ctx;
@end
Console.m
#import "Console.h"
@implementation Console
-(id)initWithContext:(JSContext *)ctx{
if (self =[super init]) {
context = ctx;
context[@"Console"] = [Console new];
}
return self;
}
-(void)log {
//所有的参数的数组
NSArray *args = [JSContext currentArguments];
NSLog(@"%@",[args componentsJoinedByString:@","]);
}
@end
调用
JSContext *context = [JSContext new];
context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
NSLog(@"%@",exception);
};
context[@"console"] = [[Console alloc]initWithContext:context];
[self loadScriptWithContext:context WithFileName:@"test.js"];