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

目录
相关文章
|
2月前
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
548 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
2月前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
145 66
|
3月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
3月前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
3月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
66 2
|
3月前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
3月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
353 4
|
3月前
|
安全 Swift iOS开发
Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法
本文深入探讨了 Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法。Swift 以其简洁、高效和类型安全的特点,结合 UIKit 丰富的组件和功能,为开发者提供了强大的工具。文章从 Swift 的语法优势、类型安全、编程模型以及与 UIKit 的集成,到 UIKit 的主要组件和功能,再到构建界面的实践技巧和实际案例分析,全面介绍了如何利用这些技术创建高质量的用户界面。
72 2
|
3月前
|
JavaScript 前端开发 开发者
JavaScript框架React vs. Vue:一场性能与易用性的较量
JavaScript框架React vs. Vue:一场性能与易用性的较量
67 0
|
3月前
|
搜索推荐 数据管理 定位技术
iOS应用开发中有多种主流框架
iOS应用开发中有多种主流框架
303 60

热门文章

最新文章

  • 1
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 2
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
  • 3
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 4
    JavaScript闭包深入剖析:性能剖析与优化技巧
  • 5
    如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
  • 6
    JavaWeb JavaScript ③ JS的流程控制和函数
  • 7
    【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
  • 8
    【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
  • 9
    【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
  • 10
    【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
  • 1
    当面试官再问我JS闭包时,我能答出来的都在这里了。
    47
  • 2
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 3
    Node.js 中实现多任务下载的并发控制策略
    34
  • 4
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    26
  • 5
    【JavaScript】深入理解 let、var 和 const
    49
  • 6
    【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
    47
  • 7
    【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
    57
  • 8
    【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
    57
  • 9
    如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
    72
  • 10
    【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
    57