前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >技术 | Hybrid载体的变化(二)

技术 | Hybrid载体的变化(二)

作者头像
icepy
发布2019-06-24 17:30:52
8190
发布2019-06-24 17:30:52
举报
文章被收录于专栏:子曰五溪子曰五溪

引擎的变化让你的JavaScript执行速度更快,并且让你的交互能力变的更为强大,iOS平台从iOS7开始提供了JavaScriptCore框架,Android平台的v8就更不用说了,至今延伸出来的包括有Node.js这种明星项目,正因为独立JS引擎让人们在追求Hybrid极致的情况下找到了Web和Native新的平衡点,比如Weex,React Native这样的移动解决方案,今天我们就要谈一谈iOS上JS的载体引擎“JavaScriptCore”,有兴趣的朋友直接阅读:https://developer.apple.com/reference/javascriptcore ,当然你也可以接着往下阅读。

额外提一句,如果没有特殊情况,所有的例子都是Swift3.1版本。

JavaScriptCore是iOS平台上提供的JavaScript虚拟机,为JavaScript的执行提供了底层资源,这是用C++编写,并且用Objective-c/Swift包装之后提供给iOS开发者使用的框架。从这里我们可以知道,JavaScriptCore至少包含:Lexer,Parser,LLInt,JIT等,理论上对于JavaScript开发者来说不懂这些不要紧,了解一下即可。Objective-C和Swift提供的JavaScriptCore稍许有一些不同,这些只是使用方式上的不同,理论上你需要看的就只是.h文件中的几个。

代码语言:javascript
复制
#ifndef JavaScriptCore_h
#define JavaScriptCore_h

#include <JavaScriptCore/JavaScript.h>
#include <JavaScriptCore/JSStringRefCF.h>

#if defined(__OBJC__) && JSC_OBJC_API_ENABLED#import "JSContext.h"
#import "JSValue.h"
#import "JSManagedValue.h"
#import "JSVirtualMachine.h"
#import "JSExport.h"

#endif
#endif /* JavaScriptCore_h */
代码语言:javascript
复制
import JavaScriptCore.JSBase
import JavaScriptCore.JSContext
import JavaScriptCore.JSContextRef
import JavaScriptCore.JSExport
import JavaScriptCore.JSManagedValue
import JavaScriptCore.JSObjectRef
import JavaScriptCore.JSStringRef
import JavaScriptCore.JSStringRefCF
import JavaScriptCore.JSTypedArray
import JavaScriptCore.JSValue
import JavaScriptCore.JSValueRef
import JavaScriptCore.JSVirtualMachine
import JavaScriptCore.JavaScript
import JavaScriptCore.WebKitAvailability

正常情况下一个JSContext代表了一个JavaScript执行环境,如果你愿意也可以通过JSVirtualMachine来提供完整的执行环境,它们之间是有不同的,一个JSVirtualMachine可以包含多个JSContext,当然你的JSContext肯定不运行包含JSVirtualMachine了,如果你要手动管理JavaScript和Native桥接对象的内存,还是需要使用这个虚拟机的,正常情况下JSVirtualMachine不应该手动去初始化它,而是要用JSContext,系统会为你分配一个JSVirtualMachine。

代码语言:javascript
复制
let jsc = JSContext()
let num = jsc?.evaluateScript("1 + 2")

使用JSContext去执行JS中定义的计算或者值,这都可以得到完整的转换,上述的一个例子只是说明了,Native如何调用JS的方式,使用"evaluateScript"直接执行任何的JS代码即可,而且如果有返回值,都可以无缝的转换成Native的对象,你可以使用print打印一下num试试效果,当然它会是一个Optional类型。

代码语言:javascript
复制
let jsc = JSContext()
jsc?.exceptionHandler = {
(context, exception) in
print("\(String(describing: exception))")
};
let num = jsc?.evaluateScript("1 + 2")
print("\(String(describing: num!))")
代码语言:javascript
复制
jsc?.evaluateScript("var tips = function(){ return 100}")
let val_number = jsc?.globalObject.invokeMethod("tips", withArguments: [])
print("\(val_number?.toNumber())")

如果想要让JS主动的调用并且向Native传输数据,也非常简单,如下:

代码语言:javascript
复制
jsc[@"callNative"] = ^(JSValue *instance, JSValue *tasks, JSValue *callback){     
    NSString *instanceId = [instance toString];     
    NSArray *tasksArray = [tasks toArray];     
    NSString *callbackId = [callback toString];
};
代码语言:javascript
复制
let logger = {
(log: String) -> Int in
return 1
};
jsc?.setObject(logger , forKeyedSubscript: "logger" as NSCopying & NSObjectProtocol)

当然在一个global环境中,以及任何Object或者Function里,有了JSValue都可以直接使用“call”或者“invokeMthod”方法来直接调用,比如:

代码语言:javascript
复制
val?.call(withArguments: ["12345"])
代码语言:javascript
复制
jsc?.globalObject.invokeMethod("logger", withArguments: ["1234567"])

当我们有了这些强大的能力后,从Native To JavaScript交互的地方都可以设计的比较完美一些,我们可以用JSExport协议来设计一个模块式的交互,对于整体项目的维护,扩展都有很大的帮助,这也是为什么说,当我们Hybrid的载体变化之后,对于这些交互,在某种程度上来说,有了质的提升。

代码语言:javascript
复制
@objc protocol JSDelegate:JSExport {    
    func callNativeModelExe(obj:JSValue) -> Int
}
@objc class JSModelExe: NSObject,JSDelegate {
func callNativeModelExe(obj: JSValue) -> Int {        
        let num = obj.toNumber();        
        print("\(String(describing: num))");        
        return 1;
}
}

你身边如果有朋友对混合领域(跨技术栈)或全栈,编程感悟感兴趣,可以转发给他们看哦,^_^先谢过啦。


本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 子曰五溪 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档