JavaScriptCore 使用

前言java

動態化是移動開發技術中的重要的一部分 ,當前廣泛的動態化方案 , 如 React Native 、Weex 、Hybrid部分解決方案及以前流行的熱修復框架 JSPatch ,背後都用到了 JavaScriptCore 框架 ,由它創建起 OC 跟 JS 語言溝通的橋樑 。git

JavaScriptCore 介紹github

JavaScriptCore 是 Safari 瀏覽器 JavaScript 引擎 ,它用來解釋和執行 JavaScript 代碼 。web

JavaScriptCore 框架是一個蘋果在 iOS7 引入的框架 ,該框架讓 Objective-C 和 JavaScript 代碼直接的交互變得更加的簡單方便 ,其實就是基於 webkit 中以C/C++實現的 JavaScriptCore 的一個 OC 版本的封裝 。瀏覽器

JavaScriptCore 和 JavaScriptCore 框架是不一樣的兩個概念 ,能夠本身理解下 。框架

OC 調用 JS 代碼函數

// 直接執行js代碼
JSContext *cxt = [JSContext new];
JSValue *val =  [cxt evaluateScript:@"(function ocCallJS() { return 'ocCallJS'})()"];
NSLog(@"%@",[val toString]); // ocCallJS

// 註冊js方法,利用JSValue調用
JSContext *cxt = [JSContext new];
JSValue *jsFunction = [cxt evaluateScript:@" (function(arg) { return arg })"];
JSValue *val = [jsFunction callWithArguments:@[@"hello objc"]];
NSLog(@"%@",[val toString]); // hello objc

這裏有幾個對象理解下fetch

JSContext atom

JSContext 對象表示 JavaScript 執行環境 ,全部 JavaScript 執行發生在上下文 , 全部 JavaScript 值中與上下文聯繫在一塊兒 。lua

JSValue

JSValue 實例是對 JavaScript 值的包裝 ( 引用 ) ,您可使用 JSValue 類在 JavaScript 和 Objective-C 或 Swift 表示之間轉換基本值(例如數字和字符串),以便在本機代碼和 JavaScript 代碼之間傳遞數據。您還可使用此類建立 JavaScript 對象,這些對象包含自定義類或 JavaScript 函數的本機對象,這些函數的實現由本機方法或塊提供。

JS 調用 OC 代碼

Block 方式

// 註冊一個 oc 方法給 js 調用
JSContext *cxt = [JSContext new];
cxt[@"nativeMethod"] = ^(NSString *msg) {
  NSLog(@"%@",msg);    //  jsCallOC
};
// js 調用 oc 的方法
[cxt evaluateScript:@"nativeMethod('jsCallOC')"];

JSExport方式

// 定義類 暴露給 js
@protocol JSBridgeObjProtocol <JSExport>
- (NSString *)fetchArticleContent;
@end

@interface JSBridgeObj : NSObject<JSBridgeObjProtocol>
@property (nonatomic, copy) NSString *articleTitle;
- (NSString *)fetchArticleContent;
@end

@implementation JSBridgeObj
- (NSString *)fetchArticleContent {
    return @"js call oc";
}
@end

// js 調用 oc 方法
JSContext *cxt = [JSContext new];
cxt[@"jsBridge"] = [JSBridgeObj new];
JSValue *val = [cxt           evaluateScript:@"jsBridge.fetchArticleContent()"];
NSLog(@"%@",[val toString]); // js call oc

JXExport 實現的協議將 OC 類及其實例方法,類方法和屬性導出到 JavaScript 代碼

這樣基於 JSContext 咱們能夠完成兩種語言間通訊

Hybrid 中的應用

APP 混合開發中 ,在 UIWebView 中獲取 JSContext 對象 ,該操做借用了蘋果的私有方法 。

// 獲取當前 WebView 的 JS 上下文
JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

不過該方法獲取 JS 上下文有幾個問題:

1 ) 獲取 JS 上下文的時機不肯定 ,好比建立 UIWebView 對象 ,UIWebView 不一樣代理回調方法中獲取到 JS 上下文都是不同的 ,並且每次加載一個新的 URL 時 , 都會廢棄舊的 JS 上下文 ,建立新的 JS 上下文 。

所以獲取 JS 上下文的時間點很重要 ,也就是在剛剛建立好新的 JS 上下文那一刻 。

只不過蘋果並無在 iOS 的 SDK 中暴露出來 ,而 macOS 的 SDK 中有獲取建立好的 JS 上下文的代理方法。

webView:didCreateJavaScriptContext:forFrame:

在 GitHub 上有這樣一個項目 TS_JavaScriptContext 能夠拿到了 JS 上下文建立的事件 ,只不過也是改獲取方法也是蘋果的私有 API , 原來項目中使用了這個庫上架蘋果應用商店沒有問題 ,如今審覈狀況不太瞭解 。

2 ) WKWebView 目前我尚未找到獲取 JS 上下文的方法

在 UIWebView 中獲取 JS 上下文的方法在 WKWebView 中是不起做用的 。

WKWebView 不支持 JavaScriptCore 的方式, 但提供 messagehandler 的方式爲 JS 與 OC 通訊 。關於 WKWebView 相關知識 ,後續再聊 。

歡迎關注公衆號:dreamlee,你的成長咱們一塊兒見證!

相關文章
相關標籤/搜索