JavaScriptCore引擎

    我们都知道WebKit是个渲染引擎,简单来说负责页面的布局,绘制以及层的合成,但是WebKit工程中不仅仅有关于渲染相关的逻辑,也集成了默认的javascript引擎--JavaScriptCore,目前Safari的js引擎也基于JSC构建,不过有一些私有的优化,总体性能相差不大。JSC的执行理念比较符合传统的引擎逻辑,它包括了2部分:解释器和简单方法JIT。解释器比较容易理解,针对某种类型的文件解释执行,在JSC中,它的目标文件是由代码构建的语法树生成的字节码文件,类似于java中的字节码,不过在JSC中字节码的执行是在基于寄存器的虚拟机中而不是基于栈,好处在于可以方便的在ARM架构处理器中使用三地址指令,减少了次数较多的出栈和入栈等指令分派以及耗时的内存IO;JIT在java虚拟机中应用比较多,针对执行较多次的热点方法进行编译为本地方法,执行效率更高,JSC中的JIT同理。

    在iOS7中,我们可以引入JSC框架,这样,我们可以oc层来操作js层代码的执行。另外JSC暴露了许多C层面的接口,我们也可以在底层来构建自定义的js执行环境,操作执行js代码,可控执行可扩展性更强。

hybrid应用构建

    既然有了这么给力的引擎,我们在构建hybrid app时可以使用JSC来代替cordova的webViewJavascriptBridge框架完成简易的接口暴露,未来在oc层逐渐可以将UI组件模块化,并通过JSExport暴露接口,由js层负责调用相应模块的初始化方法完成界面的hybrid化。

  oc端初始化一个js执行上下文JSContext对象很容易, [[JSContext alloc] init]即可,但是在hybrid app中,通过这种方式初始化JSContext与承载页面的UIWebVIew并不是同一个js环境,因此我们需要获取UIWebView对应的JSContext。但是apple官方并未提供相关的方法,不过这边难不倒某些人,有些人发现,通过KVC的方式可获取UIWebView对应的JSContext,方式如下[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]。一旦获取到对应的JSContext,我们可以做的就有很多了。

// 获取对应的JSContext
JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // 设置JSContext的错误处理函数
[context setExceptionHandler:^(JSContext *context, JSValue *value) {
NSLog(@"oc catches the exception: %@", value);
}]; // 组件化某个功能类或UIController
ShowjoyFad *sf=[ShowjoyFad new]; // 暴露改类至JSContext中,在js层的全局属性中我们可以访问该类,如window.showjoyFad
context[@"showjoyFad"]=sf;
context[@"ViewController"] = self; // 引用js层定义的函数
JSValue * abc = context[@"abc"];
// 执行
JSValue * ret = [abc callWithArguments:@[@"helloworld"]];
NSLog(@"ret: %@",[ret toString]);

    通过简单的例子可以很明显的看出JSC通信的简洁性,与android的WebView通信类似,native端可以直接讲接口注入到js上下文中,js在何时的时机调用函数。但是这里涉及到一个比较棘手的问题,JSContext的获取实在UIWebView的那个阶段呢?

    我做过一个测试:首先在UIWebView的webViewDidStartLoad阶段创建JSContext并暴露oc端的方法,在加载一级页面时js正常调用oc的方法,而跳转到二级页面中却无法执行oc的方法;而在webViewDidStartLoad阶段由于并未加载完js文件, 因此js层定义的函数在oc端无法执行。

    其次,在webVIewDidFinishLoad阶段创建JSContext并透出oc方法,由于加载js阶段在webVIewDidFinishLoad阶段之前,因此一级页面js无法调用oc方法,但是二级页面同理也是如此,但是由于js代码是在iOS的UI线程执行,因此为了让js可以调用oc方法,可以通过在js设置setTimeout来让任务放到执行队列的末端,先执行oc层的webVIewDidFinishLoad方法,待任务完成后再执行js中的异步代码,通过这种方式可以完成js调用oc方法;反过来,oc层调用js函数没有任何问题,因为在webVIewDidFinishLoad阶段js代码已执行完毕(除了异步代码)。

    为此,可以通过实现一个简易的框架来完成js层和oc层的交互,为了更好的兼容性,只有在webVIewDidFinishLoad阶段创建JSContext。而在js层则有两种方式来监测并执行oc的方法:

1,在oc层的webVIewDidFinishLoad阶段,暴露oc接口之后,通过JSContext或者UIWebView的stringByEvluateJavascriptString方法构建一个webViewDidFinishLoad事件,js端进行侦听并调用

2,简单的通过setTimeout将js的执行顺序排至队列末端

    通过上述方法,构建了一个简单的JSCBridge,但是缺点也很明显,对oc端接口暴露时机有硬性要求,并且js执行oc端的代码始终是异步,有违我们的初衷。

在下一节中,介绍利用JSC高效通信的另一种hack方法,请期待!

iOS引入JavaScriptCore引擎框架(一)的更多相关文章

  1. iOS引入JavaScriptCore引擎框架(二)

    为何放弃第一种方案 UIWebView的JSContext获取     上篇中,我们通过简单的kvc获取UIWebVIew的JSContext,但是实际上,apple并未给开发者提供访问UIWebVi ...

  2. iOS 10 中引入了 Message 框架

    WWDC 2016 上最重磅的消息之一就是在 iOS 10 中引入了 Message 框架.开发者现在可以为苹果内置的 Messages 应用开发扩展啦.通过开发一个应用扩展,你可以让用户跟应用在 M ...

  3. iOS 开发之照片框架详解(2)

    一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...

  4. IOS QuartzCore核心动画框架

    IOS QuartzCore核心动画框架 核心动画框架 使用核心动画需要引入的框架:#import CALayer: CoreAnimation CALayer就是UIView上的图层,很多的CALa ...

  5. iOS基础 - 第三方网络框架

    一.iOS网络层次结构 基于iOS提供API实现上传文件和断点续传的思路 常用iOS第三方网路框架简介 AFNetworking(AFN) ASIHTTPRequest(ASI) 另外一个常用框架 S ...

  6. iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...

  7. iOS超全开源框架、项目和学习资料汇总--数据库、缓存处理、图像浏览、摄像照相视频音频篇

    iOS超全开源框架.项目和学习资料汇总--数据库.缓存处理.图像浏览.摄像照相视频音频篇 感谢:Ming_en_long 的分享 大神超赞的集合,http://www.jianshu.com/p/f3 ...

  8. 万字+28张图带你探秘小而美的规则引擎框架LiteFlow

    大家好,今天给大家介绍一款轻量.快速.稳定可编排的组件式规则引擎框架LiteFlow. 一.LiteFlow的介绍 LiteFlow官方网站和代码仓库地址 官方网站:https://yomahub.c ...

  9. JavaScript模板引擎artTemplate.js——如何引入模板引擎?

    artTeamplate.js在github上的地址:artTemplate性能卓越的js模板引擎 引入模板引擎,就是引入外部javascript啦,并且artTemplate.js不依赖其他第三方库 ...

随机推荐

  1. 关于解决python线上问题的几种有效技术

    工作后好久没上博客园了,虽然不是很忙,但也没学生时代闲了.今天上博客园,发现好多的文章都是年终总结,想想是不是自己也应该总结下,不过现在还没想好,等想好了再写吧.今天写写自己在工作后用到的技术干货,争 ...

  2. C++中的时间函数

    C++获取时间函数众多,何时该用什么函数,拿到的是什么时间?该怎么用?很多人都会混淆. 本文是本人经历了几款游戏客户端和服务器开发后,对游戏中时间获取的一点总结. 最早学习游戏客户端时,为了获取最精确 ...

  3. C语言 · 乘法表

    问题描述 输出九九乘法表. 输出格式 输出格式见下面的样例.乘号用"*"表示. 样例输出 下面给出输出的前几行:1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94 ...

  4. 菜鸟学Struts2——Results

    在对Struts2的Action学习之后,对Struts2的Result进行学习.主要对Struts2文档Guides中的Results分支进行学习,如下图: 1.Result Types(Resul ...

  5. Linux CentOS 配置JDK环境

    一.下载JDK 下载JDK的方式有两种: 1.Linux中使用wget下载 1.使用命令安装wget yum install wget 2.下载 wget 'http://download.oracl ...

  6. WCF学习之旅—第三个示例之四(三十)

           上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九)   ...

  7. 事务日志已满,原因为“ACTIVE_TRANSACTION”

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 异常处理汇总-数据库系列  http://www.cnblogs.com/dunitia ...

  8. .Net多线程编程—任务Task

    1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 object AsyncState 表示在 ...

  9. pt-heartbeat

    pt-heartbeat是用来监测主从延迟的情况的,众所周知,传统的通过show slave status\G命令中的Seconds_Behind_Master值来判断主从延迟并不靠谱. pt-hea ...

  10. VS2015在创建项目时的一些注意事项

    一.下面是在创建一个新的项目是我最常用的,现在对他们一一做一个详细的介绍: 1.Win32控制台应用程序我平时编写小的C/C++程序都用它,它应该是用的最多的. 2.名称和解决方案名称的区别:名称是项 ...