iOS 基础--JavaScriptCore简单总结
2020-07-15 05:16
85 查看
<big><b>红酥手,黄藤酒,满城春色宫墙柳!</b></big><伊布>
- 苹果在 iOS7中增加了 JavaScriptCore 框架,而这个框架正是大大的简化 JavaScript 与 Objective-C之间的交互!它把 WebKit 的 JavaScript 引擎用 Objective-C 封装,我们可以用很简便的方法快速的接入当下流行的 JavaScript。
- JavaScriptCore可以让我们在 OC 执行的代码的任何地方运行JS 代码,不依赖 WebView
- JavaScriptCore主要就是给我们提供了 JS 代码的执行环境并进行解析运行
- 让我们应用扩展性大大提高,提供了动态去修改我们局部代码或者逻辑的思路(实现热更新),同时让我们去嵌入网页并加以调整变得轻松。
简单的总结一下关于这个框架基础使用,才浅学薄欠缺之处望包含指正!
- JSContext
它是 JavaScript 代码的运行环境,也就是作用的范围。每一个 JSContext 就是一个全局的环境变量!我们创建一个 JSContext 对象之后,可以利用它去执行相应的JavaScript 的代码操作(创建变量,定义方法等)!
- JSValue
它是为了处理 Objective-C 对象(强类型)和 JavaScript 对象(弱类型)差异的类,实现 OC 和 JS 对象的相互转化。在处理的时候 JSValue对象包裹着来自 JSContext 的值例如字符串、对象甚至是方法、还有一些错误的特殊的 JS 值类似 null 和 undefined。这个类的一些列方法(得到 Foundation 框架下得类型)就是为了我们在 OC 访问这些值时候能够正常的去访问处理!可以理解成是 JS 和 OC 之间互相转换的桥梁,下图是一个简单总结的表格!
JS类型 | JSValue转OC | Swift 类型 | OC 类型 | OC 转 JSValue |
---|---|---|---|---|
string | toString | String! | NSString | |
boolean | toBool | Bool | Bool | valueWithBool:inContext: |
number | toNumberto toDouble toInt32 toUInt32 |
NSNumber! Double Int32 UInt32 |
NSNumber double int32_tuint32_t |
valueWithDouble:inContext: valueWithInt32:inContext: valueWithUInt32:inContext: |
Date | toDate | NSDate! | NSDate | |
Arrar | toArray | [AnyObject]! | NSArray | valueWithNewArrayInContext: |
Object | toDictionary | [NSObject : AnyObject]! | NSDictionary | valueWithNewObjectInContext: |
Object | toObject toObjectOfClass: |
custom type | custom type( id类型) | valueWithObject:inContext: |
undefined | nil | nil | valueWithUndefinedInContext | |
null | NSNull | NSNull | valueWithNullInContext: |
- 我们通过代码简单理解一下 OC 和 JS交互简单实现
- 创建JSContext 对象
JSContext *context = [[JSContext alloc] init];``` - 用这个对象执行 JS 代码得到一个 JSValue 对象 ```code JSValue *jsValue = [context evaluateScript:@"23+6"];``` - JSValue 值 转换成 OC 的结果值 ```code int ocValue = [jsVlaue toInt32];``` - 执行JS函数(OC中的 Block)这样就相当于下 JS 中调用了 OC 代码 ```code // 就是把这个方法赋给 JS 的 log 这个属性(没有的话JS 会自动创建这个属性) context[@"log"] = ^(NSInteger value){ NSLog(@"-------->%ld",value);// 这里打印了掺入的第一个传入的参数 // 处理传进来的参数 NSArray *arr = [JSContext currentArguments]; // 返回一个数组 获取到的是 JS 传进去的不定参数 for (id item in arr) { NSLog(@"--->%@",item);// 依次打印了传进来的参数 } }; // 执行 JS 代码 [context evaluateScript:@"log(11,2,3)"];``` ![打印结果](http://upload-images.jianshu.io/upload_images/1523603-76924e82a8ecc542.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - 我们也可以在 OC 中使用 JS 代码结果 - 小例子:这里我写一个求 1->n 和 以及 N 阶乘 的 JS 代码然后执行结果转成 OC 的 ```code JSContext *context = [[JSContext alloc] init]; # 这里是 JS 求和以及计算阶乘的代码 [context evaluateScript:@"var numSum = function(n){var sum = 0; for( i = 0;i <= n;i++ ){ sum += i; } return sum };var factorial = function(n) { if (n < 0) return; if (n === 0) return 1; return n * factorial(n - 1) };"]; JSValue *function = context[@"numSum"]; # 调用 JS 函数方法,并返回函数的结果 传入的参数是一个给函数的传递的参数放到数组里面 JSValue *numSum = [function callWithArguments:@[@5]]; NSLog(@"把 JS结果转化成 OC结果---->%d",[numSum toInt32]);``` ![打印结果](http://upload-images.jianshu.io/upload_images/1523603-b0c193583da713ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -------- ----- - 再写一个简单的例子,我们在利用 OC 的WebView 加载 一个网页,网页上有一个 Button,点击这个 Button 我们 iOS 客户端相应的进行一些操作也就是 OC 和 HTML 交互! - 一个简单的 HTML 代码 ```code <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <input type="button" value="login" onclick="log()" /> </body> </html>
- 我们用 WebView 加载这个 HTML
UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectMake(10, 10, 300, 500)];// 创建 [self.view addSubview:webview];// 添加父视图 webview.delegate = self;// 设置代理 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];// 找到要加载的 HTML 文件 NSString *urlStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [webview loadHTMLString:urlStr baseURL:nil];// 加载``` - 我们在代理方法中获取这次加载 ```code // 每次加载网页请求都会走该方法 - (void)webViewDidFinishLoad:(UIWebView *)webView {// 获取当期WebView 相关的 context,获取 JS执行环境 JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // 我们把点击的事件获取到 也就实现了效果 context[@"log"] = ^(){ NSLog(@"点击了网页上那个的 Button!") }``` ![结果打印.gif](http://upload-images.jianshu.io/upload_images/1523603-f3dfcdb6119cfa22.gif?imageMogr2/auto-orient/strip) - JSExport > 要想在 JS 中调用OC 对象的方法和属性,需要把这些属性方法放到继承于 JSExport 的协议中,因为只有JSExport 协议中的方法才能被 JavaScript 识别!OC 对象相应的实现协议方法! - 代码示例我们先定义一个协议 ```code // 一定要继承于 JSExport @protocol JS_OC_Delegate <JSExport> @property (nonatomic, strong) NSString *name; @end``` - 在一个类中(这里是在 ViewController)中遵循代理并实现方法 ```code @synthesize name;``` - 转化执行 ```code self.name = @"云之君兮鹏"; JSContext *context = [[JSContext alloc] init]; context[@"OC_Object"] = self; [context evaluateScript:@"OC_Object.name = '小超人'"]; NSLog(@"%s--->%@",__func__,self.name);打印结果
注意一些问题:
不要在Block 中直接引用使用外面的
JSContext
对象,应该用·[JSContext currentContext];
同样的不要直接在 Block 中调用外界的 JSValue 对象,需要的话可以利用参数传递进去。
- 原因(我们在 OC 中经常回去注意的问题,避免了循环引用,相互持有!Block 可以保有变量引用,而且 JSContext 也强引用它所有的变量。)当我们使用JS 调用 OC 的回调方法时,均是在子线程中执行的,这样的话我们得注意需要的时候,要回到主线程去更新我们 UI 界面。
JSContext *context = [[JSContext alloc] init]; context[@"函数名"] = ^(类型 参数){ # 尴尬了 循环引用 JSValue *value = [JSValue valueWithNewObjectInContext:context]; # 顾德乐 正常使用 JSValue *value = [JSValue valueWithNewObjectInContext:[JSContext currentContext]]; };
今天先到这了,日后补充更新,开心就好!对了简友们节日快乐!
相关文章推荐
- IOS学习总结,基础控件+简单逻辑+简单功能+GCD。
- iOS 基础--UIEvent 事件类型简单总结(触摸、摇一摇、远程控制)
- iOS开发:JavaScriptCore.framework的简单使用--JS与OC的交互篇
- iOS开发:JavaScriptCore.framework的简单使用--JS与OC的交互篇
- 传智播客Ajax与Javascript基础知识总结下~~~基础朋友一定要看哦
- JavaScript 语言基础知识点总结
- JavaScript 实现基础--正则表达式--简单模式--
- [ios开发基础之 Core Data [1] ]Core Data数据持久性存储基础教程
- JavaScript 语言基础知识点总结(思维导图)
- iOS:Core Data 中的简单ORM
- javascript的异常处理简单总结
- 【iOS-Cocos2d游戏开发之二十】精灵的基础知识点总汇(位图操作/贴图更换/重排z轴等)以及利用CCSprite与CCLayerColor制作简单遮盖层!
- [ios开发基础之CoreData[4]]CoreData实战篇
- JavaScript 语言基础知识点总结(思维导图)
- JavaScript 语言基础知识点总结(思维导图)
- 执行代码[WebKit] JavaScriptCore解析--基础篇(二)解释器基础与JSC核心组件
- iOS开发】 CoreText 使用教程:以创建一个简单的杂志应用为例
- JavaScript 语言基础知识点总结(思维导图)
- Javascript与正则表达式个人总结与收录--基础篇
- javascript基础知识总结