让你的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月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
157 4
|
1月前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端框架
【10月更文挑战第34天】在数字化时代,后端开发如同一座桥梁,连接着用户界面与数据处理的两端。本文将通过Node.js这一轻量级、高效的平台,带领读者领略后端框架的魅力。我们将从基础概念出发,逐步深入到实战应用,最后探讨如何通过代码示例来巩固学习成果,使读者能够在理论与实践之间架起自己的桥梁。
|
1月前
|
JSON 移动开发 JavaScript
在浏览器执行js脚本的两种方式
【10月更文挑战第20天】本文介绍了在浏览器中执行HTTP请求的两种方式:`fetch`和`XMLHttpRequest`。`fetch`支持GET和POST请求,返回Promise对象,可以方便地处理异步操作。`XMLHttpRequest`则通过回调函数处理请求结果,适用于需要兼容旧浏览器的场景。文中还提供了具体的代码示例。
在浏览器执行js脚本的两种方式
|
1月前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
1月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
38 2
|
1月前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
1月前
|
安全 Swift iOS开发
Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法
本文深入探讨了 Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法。Swift 以其简洁、高效和类型安全的特点,结合 UIKit 丰富的组件和功能,为开发者提供了强大的工具。文章从 Swift 的语法优势、类型安全、编程模型以及与 UIKit 的集成,到 UIKit 的主要组件和功能,再到构建界面的实践技巧和实际案例分析,全面介绍了如何利用这些技术创建高质量的用户界面。
33 2
|
1月前
|
JSON 前端开发 API
探索iOS开发之旅:打造你的第一个天气应用
【10月更文挑战第36天】在这篇文章中,我们将踏上一段激动人心的旅程,一起构建属于我们自己的iOS天气应用。通过这个实战项目,你将学习到如何从零开始搭建一个iOS应用,掌握基本的用户界面设计、网络请求处理以及数据解析等核心技能。无论你是编程新手还是希望扩展你的iOS开发技能,这个项目都将为你提供宝贵的实践经验。准备好了吗?让我们开始吧!
|
1月前
|
JavaScript 中间件 API
Node.js进阶:Koa框架下的RESTful API设计与实现
【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
51 4
|
1月前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
59 1