六、Objective-C与JavaScript复杂对象的映射
我们在使用JavaScript调用Objective-C方法的实质是将一个OC函数设置为了JS全局对象的一个属性,当然我们也可以设置非函数的属性或者任意JSValue(或者可以转换为JSValue)的值。例如:
self.jsContext = [[JSContext alloc]init];
//向JS全局对象中添加一个获取当前Native设备类型的属性
[self.jsContext setObject:@"iOS" forKeyedSubscript:@"deviceType"];
但是如果我们想把OC自定义的一个类的对象设置为JS全局对象的某个属性,JS和OC有着完全不同的对象原理,如果不做任何处理,JS是接收不到OC对象中定义的属性和方法的。这时就需要使用到前面提到的JSExport协议,需要注意,这个协议不是用来被类遵守的,它里面没有规定任何方法,其是用来被继承定义新的协议的,自定义的协议中约定的方法和属性可以在JS中被获取到,示例如下:
OC中新建一个自定义的类:
@protocol MyObjectProtocol <JSExport>
@property(nonatomic,strong)NSString * name;
@property(nonatomic,strong)NSString * subject;
@property(nonatomic,assign)NSInteger age;
-(void)sayHi;
@end
@interface MyObject : NSObject<MyObjectProtocol>
@property(nonatomic,strong)NSString * name;
@property(nonatomic,strong)NSString * subject;
@property(nonatomic,assign)NSInteger age;
@end
@implementation MyObject
-(void)sayHi{
NSLog(@"Hello JavaScript");
}
@end
添加到JS全局对象中:
MyObject* object = [MyObject new];
object.name = @"Jaki";
object.age = 25;
object.subject = @"OC";
[jsContext setObject:object forKeyedSubscript:@"deviceObject"];
在JS运行环境中可以完整的到deviceObject对象,如下:
七、C语言风格的API解释
JavaScriptCore框架中除了包含完整的Objective-C和Swift语言的API外,也提供了对C语言的支持。
与JS运行环境相关的方法如下:
//创建一个JSContextRef组
/*
JSContextRef相当于JSContext,同一组中的数据可以共享
*/
JSContextGroupRef JSContextGroupCreate(void);
//内存引用
JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group);
//内存引用释放
void JSContextGroupRelease(JSContextGroupRef group);
//创建一个全局的运行环境
JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass);
//同上
JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass);
//内存引用
JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx);
//内存引用释放
void JSGlobalContextRelease(JSGlobalContextRef ctx);
//获取全局对象
JSObjectRef JSContextGetGlobalObject(JSContextRef ctx);
//获取JSContextRef组
JSContextGroupRef JSContextGetGroup(JSContextRef ctx);
//获取全局的运行环境
JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx);
//获取运行环境名
JSStringRef JSGlobalContextCopyName(JSGlobalContextRef ctx);
//设置运行环境名
void JSGlobalContextSetName(JSGlobalContextRef ctx, JSStringRef name);
与定义JS对象的相关方法如下:
//定义JS类
/*
参数JSClassDefinition是一个结构体 其中可以定义许多回调
*/
JSClassRef JSClassCreate(const JSClassDefinition* definition);
//引用内存
JSClassRef JSClassRetain(JSClassRef jsClass);
//释放内存
void JSClassRelease(JSClassRef jsClass);
//创建一个JS对象
JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data);
//定义JS函数
JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction);
//定义构造函数
JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor);
//定义数组
JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
//定义日期对象
JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
//定义异常对象
JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
//定义正则对象
JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
//定义函数对象
JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception);
//获取对象的属性
JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object);
//设置对象的属性
void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value);
//检查对象是否包含某个属性
bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);
//获取对象属性
JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
//定义对象属性
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception);
//删除对象属性
bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
//获取数组值
JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception);
//设置数组值
void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception);
//获取私有数据
void* JSObjectGetPrivate(JSObjectRef object);
//设置私有数据
bool JSObjectSetPrivate(JSObjectRef object, void* data);
//判断是否为函数
bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object);
//将对象作为函数来调用
JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
//判断是否为构造函数
bool JSObjectIsConstructor(JSContextRef ctx, JSObjectRef object);
//将对象作为构造函数来调用
JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
//获取所有属性名
JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object);
//进行内存引用
JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array);
//内存释放
void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array);
//获取属性个数
size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array);
//在属性名数组中取值
JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index);
//添加属性名
void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef accumulator, JSStringRef propertyName);
JS数据类型相关定义在JSValueRef中,如下:
//获取值的类型
/*
枚举如下:
typedef enum {
kJSTypeUndefined,
kJSTypeNull,
kJSTypeBoolean,
kJSTypeNumber,
kJSTypeString,
kJSTypeObject
} JSType;
*/
JSType JSValueGetType(JSContextRef ctx, JSValueRef);
//判断是否为undefined类型
bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value);
//判断是否为null类型
bool JSValueIsNull(JSContextRef ctx, JSValueRef value);
//判断是否为布尔类型
bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value);
//判断是否为数值类型
bool JSValueIsNumber(JSContextRef ctx, JSValueRef value);
//判断是否为字符串类型
bool JSValueIsString(JSContextRef ctx, JSValueRef value);
//判断是否为对象类型
bool JSValueIsObject(JSContextRef ctx, JSValueRef value);
//是否是类
bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass);
//是否是数组
bool JSValueIsArray(JSContextRef ctx, JSValueRef value);
//是否是日期
bool JSValueIsDate(JSContextRef ctx, JSValueRef value);
//比较值是否相等
bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception);
//比较值是否全等
bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b);
//是否是某个类的实例
bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception);
//创建undefined值
JSValueRef JSValueMakeUndefined(JSContextRef ctx);
//创建null值
JSValueRef JSValueMakeNull(JSContextRef ctx);
//创建布尔值
JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool boolean);
//创建数值
JSValueRef JSValueMakeNumber(JSContextRef ctx, double number);
//创建字符串值
JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string);
//通过JSON创建对象
JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string);
//将对象转为JSON字符串
JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef value, unsigned indent, JSValueRef* exception);
//进行布尔值转换
bool JSValueToBoolean(JSContextRef ctx, JSValueRef value);
//进行数值转换
double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception);
//字符串值赋值
JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception);
//值与对象的转换
JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception);
在C风格的API中,字符串也被包装成了JSStringRef类型,其中方法如下:
//创建js字符串
JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars);
JSStringRef JSStringCreateWithUTF8CString(const char* string);
//内存引用于释放
JSStringRef JSStringRetain(JSStringRef string);
void JSStringRelease(JSStringRef string);
//获取字符串长度
size_t JSStringGetLength(JSStringRef string);
//转成UTF8字符串
size_t JSStringGetUTF8CString(JSStringRef string, char* buffer, size_t bufferSize);
//字符串比较
bool JSStringIsEqual(JSStringRef a, JSStringRef b);
bool JSStringIsEqualToUTF8CString(JSStringRef a, const char* b);