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. In-Memory:在内存中创建临时表和表变量

    在Disk-Base数据库中,由于临时表和表变量的数据存储在tempdb中,如果系统频繁地创建和更新临时表和表变量,大量的IO操作集中在tempdb中,tempdb很可能成为系统性能的瓶颈.在SQL ...

  2. Git 子模块 - submodule

    有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目. 也许是第三方库,或者你 独立开发的,用于多个父项目的库. 现在问题来了:你想要把它们当做两个独立的项目,同时又想在 一个项目中使用另 ...

  3. Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作

    Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 1.实施前准备工作 1.1 服务器安装操 ...

  4. 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...

  5. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  6. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

  7. 浅谈web攻防

    CSRF 跨站请求伪造(Cross-Site Request Forgery) -原理- 从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤: 1.登录受信任网站A,并在本地生成Coo ...

  8. OpenCV人脸识别LBPH算法源码分析

    1 背景及理论基础 人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能,该术语需要和人脸检测进行区分,人脸检测是在一张图片中把人脸定位出来,完成的是搜寻 ...

  9. spring源码分析之context

    重点类: 1.ApplicationContext是核心接口,它为一个应用提供了环境配置.当应用在运行时ApplicationContext是只读的,但你可以在该接口的实现中来支持reload功能. ...

  10. 每天一个设计模式-7 生成器模式(Builder)

    每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,X ...