摘要:最近我们客户端想实现代码高亮,由于显示网页不是用的UIWebView而是用的DTCoreText,这就需要将代码片段进行加工,那就考虑prettify.js这个文件了,如何将OC的NSString传到js里并且返回处理后的结果
##JavaScriptCore简介
OS X Mavericks 和 iOS 7 引入了 JavaScriptCore 库,它把 WebKit 的 JavaScript 引擎用 Objective-C 封装,提供了简单,快速以及安全的方式接入世界上最流行的语言。
而且JavaScriptCore是开源的哦,如果感兴趣,大家可以到这里下载源码
##核心类介绍
先来看看<JavaScriptCore/JavaScriptCore.h>里面都有什么吧
里面主要有JSContext、JSValue、JSManagedValue、JSVirtualMachine、JSExport。而我们常用的只有前两个类。JSContext 是运行 JavaScript 代码的环境。一个 JSContext 是一个全局环境的实例,如果你写过一个在浏览器内运行的 JavaScript,JSContext 类似于 window。创建一个 JSContext 后,可以很容易地运行 JavaScript 代码来创建变量,做计算,甚至定义方法:
任何出自 JSContext 的值都被包裹在一个 JSValue 对象中。像 JavaScript 这样的动态语言需要一个动态类型,所以 JSValue 包装了每一个可能的 JavaScript 值:字符串和数字;数组、对象和方法;甚至错误和特殊的 JavaScript 值诸如 null 和 undefined。
JSValue 包括一系列方法用于访问其可能的值以保证有正确的 Foundation 类型,包括:
###下标值
对 JSContext 和 JSValue 实例使用下标的方式我们可以很容易地访问我们之前创建的 context 的任何值。JSContext 需要一个字符串下标,而 JSValue 允许使用字符串或整数标来得到里面的对象和数组:
你也许也有疑问他们是怎么做到的,我们可以看看JSValue的头文件可以发现
这里是用了非正式协议,这里我也写了测试代码
###调用方法
那么 如何调用一个在js写好的函数 ,并且传参数呢
JSValue 包装了一个 JavaScript 函数,我们可以从 Objective-C / Swift 代码中使用 Foundation 类型作为参数来直接调用该函数。再次,JavaScriptCore 很轻松的处理了这个桥接:
在这里用context.exceptionHandler可以来监测js中发生的错误
###实战
那么 我们要怎样实现我们真实的目的 通过prettify.js来高亮我们的代码呢 我一开始是这样写的
结果js报错了 JS Error: ReferenceError: Can’t find variable: document。
于是我去google,才发现,js里面如果有window document 等,但是JSContext通过alloc实例化,js引擎中根本没有这些,可以先实例化一个UIWebView,软后JSContext 通过[web valueForKeyPath:@”documentView.webView.mainFrame.javaScriptContext”]来获取就没问题了
修改后的代码为
控制台输出
哇塞 很酷 有没有
这里是所有代码的例子