让你的iOS应用程序支持运行JavaScript脚本:JavaScriptCore框架详解(二)

四、深入JSContext类


   看到这,你已经学会最基础的OC与JS互相问好(交互)。下面我们再来深入看下JSContext中的属性和方法。


   创建JSContext对象有如下两种方式:


//创建一个新的JS运行环境

- (instancetype)init;

//创建一个新的JS运行环境 并关联到某个虚拟机对象上

- (instancetype)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;

   执行JS代码有如下两个方法:


//执行JS代码 结果将封装成JSValue对象返回

- (JSValue *)evaluateScript:(NSString *)script;

//作用同上

- (JSValue *)evaluateScript:(NSString *)script withSourceURL:(NSURL *)sourceURL NS_AVAILABLE(10_10, 8_0);

   下面的属性和方法可以获取到JS运行环境中的一些信息:


//当前的JS运行环境 当JS调用OC方法时,在OC方法中可以用此方法获取到JS运行环境

+ (JSContext *)currentContext;

//获取当前执行的JS函数,当JS调用OC方法时,在OC方法中可以用此方法获取到执行的函数

+ (JSValue *)currentCallee;

//获取当前执行的JS函数中的this指向的对象

+ (JSValue *)currentThis;

//获取当前执行函数的参数列表,当JS调用OC方法时,在OC方法中可以用此方法获取到执行的函数的参数列表

+ (NSArray *)currentArguments;

//获取当前JS运行环境的全局对象

@property (readonly, strong) JSValue *globalObject;

//当运行的JavaScript代码抛出了未捕获的异常时,这个属性会被赋值为抛出的异常

@property (strong) JSValue *exception;

//设置为一个异常捕获的block,如果异常被此block捕获,exception属性就不再被赋值了

@property (copy) void(^exceptionHandler)(JSContext *context, JSValue *exception);

//当前运行环境所关联的虚拟机

@property (readonly, strong) JSVirtualMachine *virtualMachine;

//当前运行环境名称

@property (copy) NSString *name;

//获取当前JS运行环境全局对象上的某个属性

- (JSValue *)objectForKeyedSubscript:(id)key;

//设置当前JS运行环境全局对象上的属性

- (void)setObject:(id)object forKeyedSubscript:(NSObject <NSCopying> *)key;

//将C语言环境的JS运行环境转换为OC环境的JS运行环境

+ (JSContext *)contextWithJSGlobalContextRef:(JSGlobalContextRef)jsGlobalContextRef;

//C语言环境的JS运行上下文

@property (readonly) JSGlobalContextRef JSGlobalContextRef;

五、深入JSValue类


   JSValue是JavaScript与Objective-C之间的数据桥梁。在Objective-C中调用JS脚本或者JS调用OC方法都可以使用JSValue来传输数据。其中属性和方法示例如下:


//所对应的JS运行环境

@property (readonly, strong) JSContext *context;

//在指定的JS运行环境中创建一个JSValue对象

+ (JSValue *)valueWithObject:(id)value inContext:(JSContext *)context;

//创建布尔值

+ (JSValue *)valueWithBool:(BOOL)value inContext:(JSContext *)context;

//创建浮点值

+ (JSValue *)valueWithDouble:(double)value inContext:(JSContext *)context;

//创建32位整型值

+ (JSValue *)valueWithInt32:(int32_t)value inContext:(JSContext *)context;

//创建32位无符号整形值

+ (JSValue *)valueWithUInt32:(uint32_t)value inContext:(JSContext *)context;

//创建空的JS对象

+ (JSValue *)valueWithNewObjectInContext:(JSContext *)context;

//创建空的JS数组

+ (JSValue *)valueWithNewArrayInContext:(JSContext *)context;

//创建JS正则对象

+ (JSValue *)valueWithNewRegularExpressionFromPattern:(NSString *)pattern flags:(NSString *)flags inContext:(JSContext *)context;

//创建JS错误信息

+ (JSValue *)valueWithNewErrorFromMessage:(NSString *)message inContext:(JSContext *)context;

//创建JS null值

+ (JSValue *)valueWithNullInContext:(JSContext *)context;

//创建JS undefined值

+ (JSValue *)valueWithUndefinedInContext:(JSContext *)context;

JavaScript中的数据类型和Objective-C的数据类型还是有着很大的差异,其中对应关系如下:


Objective-C  JavaScript

nil undefined

NSNull null

NSString string

NSNumber number boolean

NSDictionary    Object

NSArray Array

NSDate Date  

Block Function

id Object

Class Object

下面这些方法可以将JSValue值转换为Objective-C中的数据类型:


//将JSValue转换为OC对象

- (id)toObject;

//将JSValue转换成特定OC类的对象

- (id)toObjectOfClass:(Class)expectedClass;

//将JSValue转换成布尔值

- (BOOL)toBool;

//将JSValue转换成浮点值

- (double)toDouble;

//将JSValue转换成32位整型值

- (int32_t)toInt32;

//将JSValue转换成32位无符号整型值

- (uint32_t)toUInt32;

//将JSValue转换成NSNumber值

- (NSNumber *)toNumber;

//将JSValue转换成NSString值

- (NSString *)toString;

//将JSValue转换成NSDate值

- (NSDate *)toDate;

//将JSValue转换成NSArray值

- (NSArray *)toArray;

//将JSValue转换成NSDictionary值

- (NSDictionary *)toDictionary;

//获取JSValue对象中某个属性的值

- (JSValue *)valueForProperty:(NSString *)property;

//设置JSValue对象中某个属性的值

- (void)setValue:(id)value forProperty:(NSString *)property;

//删除JSValue对象中的某个属性

- (BOOL)deleteProperty:(NSString *)property;

//判断JSValue对象中是否包含某个属性

- (BOOL)hasProperty:(NSString *)property;

//定义JSValue中的某个属性 这个方法和JavaScript中Object构造函数的defineProperty方法一致

/*

第2个参数设置此属性的描述信息 可以设置的键值如下:

NSString * const JSPropertyDescriptorWritableKey;//设置布尔值 是否可写

NSString * const JSPropertyDescriptorEnumerableKey;//设置布尔值 是否可枚举

NSString * const JSPropertyDescriptorConfigurableKey;//设置布尔值 是否可配置

NSString * const JSPropertyDescriptorValueKey;//设置此属性的值

NSString * const JSPropertyDescriptorGetKey;//设置此属性的get方法

NSString * const JSPropertyDescriptorSetKey;//设置此属性的set方法

以上set、get方法的键和value、可写性的键不能同时存在,其语法是JavaScript保持一致

*/

- (void)defineProperty:(NSString *)property descriptor:(id)descriptor;

//获取JS数组对象某个下标的值

- (JSValue *)valueAtIndex:(NSUInteger)index;

//设置JS数组对象某个下标的值

- (void)setValue:(id)value atIndex:(NSUInteger)index;

//判断此对象是否为undefined

@property (readonly) BOOL isUndefined;

//判断此对象是否为null

@property (readonly) BOOL isNull;

//判断此对象是否为布尔值

@property (readonly) BOOL isBoolean;

//判断此对象是否为数值

@property (readonly) BOOL isNumber;

//判断此对象是否为字符串

@property (readonly) BOOL isString;

//判断此对象是否为object对象

@property (readonly) BOOL isObject;

//判断此对象是否为数组

@property (readonly) BOOL isArray;

//判断此对象是否为日期对象

@property (readonly) BOOL isDate;

//比较两个JSValue是否全相等 对应JavaScript中的===

- (BOOL)isEqualToObject:(id)value;

//比较两个JSValue对象的值是否相等 对应JavaScript中的==

- (BOOL)isEqualWithTypeCoercionToObject:(id)value;

//判断某个对象是否在当前对象的原型链上

- (BOOL)isInstanceOf:(id)value;

//如果JSValue是Function对象 可以调用此方法 和JavaScript中的call方法一致

- (JSValue *)callWithArguments:(NSArray *)arguments;

//如果JSValue是一个构造方法对象 可以调用此方法 和JavaScript中使用new关键字一致

- (JSValue *)constructWithArguments:(NSArray *)arguments;

//用此对象进行函数的调用 当前对象会被绑定到this中

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

//将CGPoint转换为JSValue对象

+ (JSValue *)valueWithPoint:(CGPoint)point inContext:(JSContext *)context;

//将NSRange转换为JSValue对象

+ (JSValue *)valueWithRange:(NSRange)range inContext:(JSContext *)context;

//将CGRect转换为JSValue对象

+ (JSValue *)valueWithRect:(CGRect)rect inContext:(JSContext *)context;

//将CGSize转换为JSValue对象

+ (JSValue *)valueWithSize:(CGSize)size inContext:(JSContext *)context;

//转换成CGPoint数据

- (CGPoint)toPoint;

//转换成NSRange数据

- (NSRange)toRange;

//转换成CGRect数据

- (CGRect)toRect;

//转换为CGSize数据

- (CGSize)toSize;

//将C风格的JSValueRef对象转换为JSValue对象

+ (JSValue *)valueWithJSValueRef:(JSValueRef)value inContext:(JSContext *)context;

其实在JavaScriptCore框架中还有一个JSManagerValue类,这个的主要作用是管理内存。虽然我们在编写Objective-C代码时有强大的自动引用技术(ARC技术),我们一般无需关心对象的内存问题,在编写JavaScript代码时也有强大的垃圾回收机制(这种机制下甚至连循环引用都不是问题),但是在OC和JS混合开发时,就很容易出现问题了,比如一个JS垃圾回收机制释放掉的对象OC中却还在用,反过来也是一样。JSManagerValue对JSValue进行了一层包装,它可以保证在适合时候使用这个对象时对象都不会被释放,其中方法如下:


//创建JSVlaue对象的包装JSManagerValue

+ (JSManagedValue *)managedValueWithValue:(JSValue *)value;

+ (JSManagedValue *)managedValueWithValue:(JSValue *)value andOwner:(id)owner;

- (instancetype)initWithValue:(JSValue *)value;

//获取所包装的JSValue对象

@property (readonly, strong) JSValue *value;

上一篇:2019年春晚借深圳展现未来,你听到科技创新的时代最强音了吗?


下一篇:在QM榜单中名列前茅,斗鱼做对了什么?