JavaScriptCore (一)

 JavaScriptCore   什么是JavaScriptCore


(一)JavaScriptCore 是一个提供网页Javascript引擎接口的的框架。框架提供了强大的功能,可以实现Swift/Objective-C 和 Javascript 代码之间的交互。(React Native 技术 就是对JavaScriptCore 强大功能的一个实际运用。)

(二)JavaScriptCore是线程安全的,它里头有几个核心组件:JSVirtualMachine, JSContext, JSValue


JSVirtualMachine

1. JSVirtualMachine(虚拟机制类)  : JavaScript代码其实是在JSVirtualMachine类提供的环境中执行,通常不必直接对它进行操作,除非需要进行并发执行JavaScript,因为一个JSVirtualMachine是不能再同一时间执行多线程任务的,所以此时需要使用多个虚拟机制。

2. 每一个JSVirtualMachine实例都与自己的堆栈和垃圾回收机制,所以不能再不同的虚拟机制之间传递对象信息,因为虚拟机制的垃圾回收器不知道怎样处理来至其它堆栈的值。需要使用到它有两个主要情况:为了并发执行JavaScript;JavaScript 和 Objecive-C/Swift 之间桥接对象的内存管理(注意使用JSManagedValue)。


JSContext

1. JSContext OC 支持 JavaScript 执行的环境对象, 是运行 JavaScript 代码的环境。OC 语言 JavaScript之间的桥接,可以依赖它来实现。一个 JSContext 是一个全局环境的实例,每一个JavaScript context都隶属于一个虚拟机。同虚拟机制类不同,不同context之间是可以进行对象信息传递的(一个虚拟机可以内含多个context,只要将它们放置在同一个虚拟机制下)

       2. JSContext 通常与UIWebView一起使用,那应该怎样得到webview中加载的javascript代码呢,不再通过URL拦截,使用JSContext的方法直接取 UIWebView context,然后进行对JS操作:context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

       3. 当然也可以使(evaluateScript:)方法添加Javascript代码到context中,或者执行javascript代码。


JSValue

1. JSValue JavaScript值的一个引用实例对象,它可以代表任何JavaScript值类型,一个JSValue实例是搬到在它所依赖的JSContext中的,任何来至这个context中的值都会是一个JSValue类型。

         a)可实现 OC|Swift JavaScript 中基本数据类型的转换,并能够实现原生和JavaScript之间的数据传递,

         b)可以创建JavaScript对象,通过原生的方法或者blocks提供其中的JavaScript函数实现。

2. evaluateScript: 执行javascript代码,返回值JSValue


        

(三)下面直接上代码,演示一下如何使用JavaScriptCore框架来实现 Javascript 到 native的调用过程。



         /// context 中添加 javascript 代码

        JSContext *context = [[JSContext alloc] init];

        [context evaluateScript:@"var num = 5 + 5"];

        [context evaluateScript:@"var names = ['Grace', 'Ada', 'Margaret']"];

        [context evaluateScript:@"var triple = function(value) { return value * 3 }"];

        [context evaluateScript:@"var sendValueToNative = ({'name1':'1','value1':'a','name2':'2','value2':'b' })"];



        /// 利用 context 执行 javascript 代码

        JSValue *tripleNum = [context evaluateScript:@"triple(num)"];

        NSLog(@"Tripled: %d", [tripleNum toInt32]);

        // Tripled: 30

        JSValue *value1 = [context evaluateScript:@"sendValueToNative"];

        NSLog(@"value1 = %@",[value1 toDictionary]);

        //value1 = {name1 = 1; name2 = 2;  value1 = a; value2 = b;}



        /*

         JSContext JSValue 实例使用下标的方式我们可以很容易地访问我们之前创建的 context 的任何值。JSContext 需要一个字符串下标,而 JSValue 允许使用字符串或整数标来得到里面的对象和数组:

         */

        JSValue *names = context[@"names"];

        JSValue *initialName = names[0];

        NSLog(@"The first name: %@", [initialName toString]);

        // The first name: Grace



        /*

         JSContext 还有另外一个有用的招数:通过设置上下文的 exceptionHandler 属性,你可以观察和记录语法,类型以及运行时错误。 exceptionHandler 是一个接收一个 JSContext 引用和异常本身的回调处理:

         */

        context.exceptionHandler = ^(JSContext *context, JSValue *exception) {

            NSLog(@"JS Error: %@", exception);

        };

        [context evaluateScript:@"function multiply(value1, value2) { return value1 * value2 "];

        // JS Error: SyntaxError: Unexpected end of script





        /*

         1. 现在我们知道了如何从 JavaScript 环境中提取值以及如何调用其中定义的函数。那么反向呢?我们怎样才能从 JavaScript 访问我们在 Objective-C Swift 定义的对象和方法?

         2. JSContext 访问我们的本地客户端代码的方式主要有两种:block JSExport 协议。

         3. 当一个 Objective-C block 被赋给 JSContext 里的一个标识符,JavaScriptCore 会自动的把 block 封装在 JavaScript 函数里。这使得在 JavaScript 中可以简单的使用 Foundation Cocoa 类,所有的桥接都为你做好了。

         4. 由于 block 可以保有变量引用,而且 JSContext 也强引用它所有的变量,为了避免强引用循环需要特别小心。避免保有你的 JSContext 或一个 block 里的任何 JSValue。相反,使用 [JSContext currentContext] 得到当前上下文,并把你需要的任何值用参数传递。

         */

        context[@"simplifyString"] = ^(NSString *input) {

            NSMutableString *mutableString = [input mutableCopy];

            CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformToLatin, NO);

            CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);

            return mutableString;

        };

        NSLog(@"%@", [context evaluateScript:@"simplifyString('안녕하새요!')"]);


        context[@"sendValue"] =

        ^(NSDictionary *objc)

        {

            return objc[@"name1"];

        };

        JSValue *value2 =  [context evaluateScript:@"sendValue({'name1':'one','value1':'a','name2':'2','value2':'b' })"];

        NSLog(@"value2 = %@",[value2 toString]);

        // value2 = one




        //注册一个匿名函数

        JSValue *jsFunction = [context evaluateScript:@" (function(string) { return 'hello objc '+ string })"];

        //调用

        JSValue *value3 = [jsFunction callWithArguments:@[@"coding is beauty"]];

        NSLog(@"value3 = %@",[value3 toString]);

        //value3 = hello objc coding is beauty


        // 再注册执行一个有名函数,并调用callWithArguments这个方法进行参数传值。(JS里面函数也是对象)

        [context evaluateScript:@"function addfun(a,b) {return a+b}"];

        JSValue *n = [context[@"addfun"] callWithArguments:@[@2, @3]];

        NSLog(@"---%@", @([n toInt32]));//---5






(四)补充。

1. Javascript 的跨平台性非常好,因此所讨论的技术其实就是如何实现Native与Javascript之间的通讯。这样做的使用示例最直接的就是实现一个WebView 和 native 的交互。JavaScriptCore就是为之而设计。

2. UIWebView 中有提供了几个代理方法,利用其中的URL拦截或者js注入等可以实现一些简单的网页到native原生的交互。

3. 罗列几篇参考文章,

//http://nshipster.cn/javascriptcore/

//https://www.raywenderlich.com/124075/javascriptcore-tutorial

//http://www.jianshu.com/p/a329cd4a67ee



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值