让你的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);

目录
相关文章
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1515 4
|
JavaScript 前端开发 API
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端框架
【10月更文挑战第34天】在数字化时代,后端开发如同一座桥梁,连接着用户界面与数据处理的两端。本文将通过Node.js这一轻量级、高效的平台,带领读者领略后端框架的魅力。我们将从基础概念出发,逐步深入到实战应用,最后探讨如何通过代码示例来巩固学习成果,使读者能够在理论与实践之间架起自己的桥梁。
|
JavaScript Shell C#
多种脚本批量下载 Docker 镜像:Shell、PowerShell、Node.js 和 C#
本项目提供多种脚本(Shell、PowerShell、Node.js 和 C#)用于批量下载 Docker 镜像。配置文件 `docker-images.txt` 列出需要下载的镜像及其标签。各脚本首先检查 Docker 是否安装,接着读取配置文件并逐行处理,跳过空行和注释行,提取镜像名称和标签,调用 `docker pull` 命令下载镜像,并输出下载结果。使用时需创建配置文件并运行相应脚本。C# 版本需安装 .NET 8 runtime。
1061 3
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
4205 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
iOS开发 开发者 Windows
uniapp云打包ios应用证书的获取方法,生成指南
打包用到的一共两个文件,一个是p12格式的私钥证书,一个是证书profile文件。其中生成p12证书的时候,按照官网的教程,是需要MAC电脑来协助做的,主要是生成一些csr文件和导出p12证书等。其实这些步骤也可以借助一些其他的工具来实现,不一定使用mac电脑,用windows电脑也可以创建。
1505 0
|
JSON 移动开发 JavaScript
在浏览器执行js脚本的两种方式
【10月更文挑战第20天】本文介绍了在浏览器中执行HTTP请求的两种方式:`fetch`和`XMLHttpRequest`。`fetch`支持GET和POST请求,返回Promise对象,可以方便地处理异步操作。`XMLHttpRequest`则通过回调函数处理请求结果,适用于需要兼容旧浏览器的场景。文中还提供了具体的代码示例。
316 5
在浏览器执行js脚本的两种方式
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
509 2