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

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

六、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);

目录
相关文章
|
1月前
|
JavaScript 前端开发 测试技术
使用Selenium执行JavaScript脚本:探索Web自动化的新领域
本文介绍了如何在Selenium中使用JavaScript解决自动化测试中的复杂问题。Selenium的`execute_script`函数用于同步执行JS,例如滑动页面、操作时间控件等。在滑动操作示例中,通过JS将页面滚动到底部,点击下一页并获取页面信息。对于只读时间控件,利用JS去除readonly属性并设置新日期。使用JS扩展了Selenium的功能,提高了测试效率和精准度,适用于各种自动化测试场景。
43 1
|
1月前
|
JavaScript 前端开发 Java
liteflow规则引擎 执行Javascript脚本
liteflow规则引擎 执行Javascript脚本
39 1
|
2月前
|
消息中间件 Web App开发 JavaScript
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
74 0
|
12天前
|
Web App开发 缓存 JavaScript
|
1月前
|
JSON JavaScript 前端开发
JS逆向快速定位关键点之9大通用hook脚本
JS逆向快速定位关键点之9大通用hook脚本
|
1月前
|
JavaScript 前端开发 开发者
如果你想在钉钉环境中运行JavaScript脚本
【2月更文挑战第17天】如果你想在钉钉环境中运行JavaScript脚本
34 6
|
2月前
|
监控 JavaScript 前端开发
统计项目代码行数轻松搞定:使用 Node.js 脚本自动统计代码量
统计项目代码行数轻松搞定:使用 Node.js 脚本自动统计代码量
58 0
|
2月前
|
JavaScript 持续交付 开发工具
Git自动化利器:使用Node.js脚本定制化提交消息处理
Git自动化利器:使用Node.js脚本定制化提交消息处理
58 0
|
2月前
|
JavaScript 前端开发 算法
【Node.js 版本过高】运行前端时,遇到错误 `Error: error:0308010C:digital envelope routines::unsupported`
【Node.js 版本过高】运行前端时,遇到错误 `Error: error:0308010C:digital envelope routines::unsupported`
66 0
|
安全 JavaScript 前端开发
Javascript框架库漏洞验证
Javascript框架库漏洞验证
2403 0
Javascript框架库漏洞验证