JavaScriptCore-b
JavaScriptCore提供了JavaScript和Objective-C桥接的Obj-C API。JavaScriptCore提供了让我们脱离UIWebView执行JavaScript脚本的能力,以及使用现代的Objective-C语法(例如Blocks和下标)在Objective-C和JavaScript之间无缝的传递值或者对象。借助JavaScriptCore,我们只需要很少的代码就可以完成OC与JS的交互通信,下面让我们一睹它的风采。同样,这篇文章会用JavaScriptCore有关API重写上一篇文章
一、JavaScriptCore概述
使用JavaScriptCore需要导入头文件"#import <JavaScriptCore/JavaScriptCore.h>",进入头文件我们会看到里面的类不多,只有下面5个:
|
1
2
3
4
5
|
#import "JSContext.h"#import "JSValue.h"#import "JSManagedValue.h"#import "JSVirtualMachine.h"#import "JSExport.h" |
JSContext: 代表JavaScript的运行环境,创建JSContext后,可以来执行JavaScript代码。
JSValue: 代表JavaScript实体,一个JSValue可以是JavaScript中的任意类型:字符串和数字;数组、对象和方法;甚至错误和特殊的 JavaScript 值诸如 null 和 undefined。任何JSContext的值都被包裹在一个JSValue对象中。
JSManagedValue: 本质上是一个JSValue,用来处理内存管理中的一些特殊情形,它能帮助OC引用技术和JS垃圾回收这两种内存管理机制之间进行正确的转换。
JSExport: 这是一个协议,可以用这个协议来将原生对象导出给JavaScript,这样原生对象的属性或方法就成为了JavaScript的属性或方法。
JSVirtualMachine: 代表一个对象空间,拥有自己的堆结构和垃圾回收机制,是运行JS代码的基础。大部分情况下不需要和它直接交互,除非要处理一些特殊的多线程或者内存管理问题。
二、JavaScriptCore深入
1. 方法调用
a. OC调用JS
|
1
2
3
4
5
6
7
8
|
//使用UIWebView执行js脚本的方法- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;//使用JSContext执行js脚本的方法- (JSValue *)evaluateScript:(NSString *)script;//使用JSValuet执行js脚本的方法- (JSValue *)callWithArguments:(NSArray *)arguments; |
b. JS调用OC
有两种方式:block和JSExport协议
通过block可以直接讲某个功能的函数,注入给JSContext,使其调用,但要注意内存泄露
通过继承JSExport协议,可以将OC的方法,属性注入给JSContext,然后调用
2. 错误处理
当JavaScript运行时出现异常,会回调JSContext的exceptionHandler中设置的Block,然后在OC端进行错误处理
|
1
2
3
|
context.exceptionHandler = ^(JSContext *context, JSValue *exception) { NSLog(@"JS Error: %@", exception);}; |
3. 内存管理
Objective-C的内存管理机制是引用计数,JavaScript的内存管理机制是垃圾回收。在大部分情况下,JavaScriptCore能做到在这两种内存管理机制之间无缝无错转换,但也有少数情况需要使用到JSManagedValue对象解决,后面会给出对应链接。
三、使用JavaScriptCore重写
沿用之前的示例,其他地方均无改动,只修改了两边交互的相关代码:
OC端:
1. 初始化JScontext
|
1
|
self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; |
2. 注入JS代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
__block typeof(self) weakSelf = self;//JS调用OC方法列表self.jsContext[@"showMobile"] = ^ { dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf showMsg:@"我是下面的小红 手机号是:18870707070"]; });};self.jsContext[@"showName"] = ^ (NSString *name) { dispatch_async(dispatch_get_main_queue(), ^{ NSString *info = [NSString stringWithFormat:@"你好 %@, 很高兴见到你",name]; [weakSelf showMsg:info]; });};void (^_showSendMsg) (NSString *num, NSString *msg) = ^ (NSString *num, NSString *msg) { dispatch_async(dispatch_get_main_queue(), ^{ NSString *info = [NSString stringWithFormat:@"这是我的手机号: %@, %@ !!",num,msg]; [self showMsg:info]; });};[self.jsContext setObject:_showSendMsg forKeyedSubscript:@"showSendMsg"]; |
3. 执行JS端代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//OC调用JS方法列表- (IBAction)btnClick:(UIButton *)sender { if (sender.tag == 123) { //使用jsContext [self.jsContext evaluateScript:@"alertMobile()"]; } if (sender.tag == 234) { //使用webView [self.webView stringByEvaluatingJavaScriptFromString:@"alertName('小红')"]; } if (sender.tag == 345) { //使用jsValue JSValue *jsValue = [self.jsContext objectForKeyedSubscript:@"alertSendMsg"]; [jsValue callWithArguments:@[@"18870707070",@"周末爬山真是件愉快的事情"]]; }} |
JS端:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//提供给OC调用JS的方法列表function alertMobile() { alert('我是上面的小黄 手机号是:13300001111')}function alertName(msg) { alert('你好 ' + msg + ', 我也很高兴见到你')}function alertSendMsg(num,msg) { alert('这是我的手机号:' + num + ',' + msg + '!!')}//JS响应方法列表function btnClick1() { showMobile()}function btnClick2() { showName('xiaohuang')}function btnClick3() { showSendMsg('13300001111', 'Go Climbing This Weekend !!!')} |
了解过JavaScriptCore的原理及核心文件,核心类的作用,再过来上手重写,已经没有什么什么阻碍了,但是仍然有需要注意的地方。因为JavaScript是单线程的,在JS调用OC的代码都是在线程中执行的,所以和界面相关操作我们需要切换到主线程来刷新,其他流程和之前保持一致,学习这一部分参考了很多其他资料,文章后面给出了有关JavaScriptCore的介绍和实现原理解析的文章链接,有兴趣的同学可以传送之深入学习
四、后记
苹果的技术每年都会更新,在JavaScript这一块,每年也会出现新的惊喜,iOS8发布的时候,苹果又推出了WKWebView,对之前的UIWebView进行了一次脱胎换骨的重构(将UIWebView和UIWebViewDelegate重构成了14个类和3个协议),功能也更加完善和强大,稳定性和性能也明显提高。之前看到过一篇文章,详细介绍了WKWebView的相关API,对我了解这一模块提供了很大的帮助,后面我也系统的看完了整个WKWebView的API,受益匪浅,看的时候,我没有直接过去看这篇文章,而是先自己通读API然后对比这篇文章,查看理解方面的出入,同时也加深了印象,同学们也可以借鉴这种方式。下一篇文章,我们使用WKWebView的相关API来完成这个示例
戳这里:本文的DEMO地址欢迎star
参考资料(戳这里):
> http://nshipster.cn/javascriptcore/
> https://hjgitbook.gitbooks.io/ios/content/04-technical-research/04-javascriptcore-note.html
JavaScriptCore-b的更多相关文章
- How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧
个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...
- iOS引入JavaScriptCore引擎框架(一)
JavaScriptCore引擎 我们都知道WebKit是个渲染引擎,简单来说负责页面的布局,绘制以及层的合成,但是WebKit工程中不仅仅有关于渲染相关的逻辑,也集成了默认的javascri ...
- 判断js引擎是javascriptCore或者v8
来由 纯粹的无聊,一直在搜索JavaScriptCore和SpiderMonkey的一些信息,却无意中学习了如何在ios的UIWebView中判断其js解析引擎的方法: if (window.de ...
- DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?
写在前面 阅读目录: 具体业务场景 业务需求变化 "愚蠢"的应对 消息列表实现 消息详情页实现 消息发送.回复.销毁等实现 回到原点的一些思考 业务需求变化,领域模型变化了吗? 对 ...
- CSS3 3D立方体效果-transform也不过如此
CSS3系列已经学习了一段时间了,第一篇文章写了一些css3的奇技淫巧,原文戳这里,还获得了较多网友的支持,在此谢过各位,你们的支持是我写文章最大的动力^_^. 那么这一篇文章呢,主要是通过一个3D立 ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)
上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...
- DDD 领域驱动设计-两个实体的碰撞火花
上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...
- node中的Stream-Readable和Writeable解读
在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...
- C#~异步编程再续~await与async引起的w3wp.exe崩溃-问题友好的解决
返回目录 关于死锁的原因 理解该死锁的原因在于理解await 处理contexts的方式,默认的,当一个未完成的Task 被await的时候,当前的上下文将在该Task完成的时候重新获得并继续执行剩余 ...
随机推荐
- Apache Shiro 集成-Cas
http://blog.csdn.net/peterwanghao/article/details/8825008 Shiro集成CAS是在1.2版本里新增的功能. Shiro-cas模块将应用作为C ...
- How to easily concatenate text based on criteria in Excel? 如何将Excel中的文本按条件合并
To combine text with the unique ID numbers, you can extract the unique values first and then create ...
- android常见错误-Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
在andorid进行调试的过程中,出现下面的错误: 解决方法: 修改一下应用程序描述符: <manifest xmlns:android="http://schemas.android ...
- 【web开发学习笔记】ibatis学习总结
ibatis学习总结 ibatis数据库配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCT ...
- VS2012执行Cocos2d-xTest案例载入失败解决方式
编译cocos2d-x,一直提示载入失败 通过搜索,解决方式例如以下: 第一步,通过命令提示行工具进入VS安装文件夹下的%VS2012home%Common7\IDE 第二部,运行devenv.exe ...
- 数据结构与算法/leetcode/lintcode题解
http://algorithm.yuanbin.me/zh-hans/index.html
- (转载)myeclipse项目名称重命名
myeclipse项目名称重命名 实例1 今天晚上在做一个jsp唱片显示的实例,myeclipse项目名称原本想写music结果写成了musci.这就需要项目名称的重命名,单纯的使用 “重构--> ...
- java String的比较,BOX装箱拆箱,以及面向对象的小代码
package cn.hncu.day2; public class StringDemo { public static void main(String[] args) { String str1 ...
- Java基础知识强化之网络编程笔记08:TCP之客户端键盘录入服务器控制台输出
1. 客户端: package cn.itcast_08; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...
- Bash判断文件是否存在
#!/bin/bash if [ -f filename ]; then echo 'file exist' else echo 'file not exist' fi