麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > JavaScript > 正文

JavaScriptCore詳解

2019-11-06 09:59:02
字體:
來源:轉載
供稿:網友

本博客主要分以下幾個方面來介紹iOS中的javaScriptCore

JavascriptCore簡介JavaScriptCore中主要的類JSContextJSValueJSExportJSManagedValueJSVirtualMachineNative Code 和 JS 之間的互相調用Native Code 與UIWebView中的JS交互Native Code 與JS文件直接交互

JavaScriptCore簡介

JavaScriptCore背景

iOS中的JavaScriptCore.framework其實只是基于webkit(Safari的瀏覽器引擎)中以C/C++實現的JavaScriptCore的一個包裝,在iOS7中,Apple將其作為一個標準庫供開發者使用

JavaScriptCore主要功能

JavaScriptCore主要是對JS進行解析和提供執行環境。代碼是開源的,JavaScriptCore源碼JavaScriptCore可以讓我們脫離webview直接運行我們的jsJavaScriptCore提供一種動態局部升級和更新的邏輯,大大提高應用的可擴展性對手機內嵌web模式的新嘗試點,即通過Native+JS file的方式取代webview的方式

JavaScriptCore中主要的類

JSContext --- 在OC中創建JavaScript運行的上下文環境

- (instancetype)init; // 創建JSContext對象,獲得JavaScript運行的上下文環境 // 在特定的對象空間上創建JSContext對象,獲得JavaScript運行的上下文環境 - (instancetype)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine; // 運行一段js代碼,輸出結果為JSValue類型 - (JSValue *)evaluateScript:(NSString *)script; // iOS 8.0以后可以調用此方法 - (JSValue *)evaluateScript:(NSString *)script withSourceURL:(NSURL *)sourceURL NS_AVAILABLE(10_10, 8_0); // 獲取當前正在運行的JavaScript上下文環境 + (JSContext *)currentContext; // 返回結果當前執行的js函數 function () { [native code] } ,iOS 8.0以后可以調用此方法 + (JSValue *)currentCallee NS_AVAILABLE(10_10, 8_0); // 返回結果當前方法的調用者[object Window] + (JSValue *)currentThis; // 返回結果為當前被調用方法的參數 + (NSArray *)currentArguments; // js的全局變量 [object Window] @PRoperty (readonly, strong) JSValue *globalObject;

JSValue --- JavaScript中的變量和方法,可以轉成OC數據類型,每個JSValue都和JSContext相關聯并且強引用context

@textblock Objective-C type | JavaScript type --------------------+--------------------- nil | undefined NSNull | null NSString | string NSNumber | number, boolean NSDictionary | Object object NSArray | Array object NSDate | Date object NSBlock (1) | Function object (1) id (2) | Wrapper object (2) Class (3) | Constructor object (3) @/textblock // 在context創建BOOL的JS變量 + (JSValue *)valueWithBool:(BOOL)value inContext:(JSContext *)context; // 將JS變量轉換成OC中的BOOL類型 - (BOOL)toBool; // 修改JS對象的屬性的值 - (void)setValue:(id)value forProperty:(NSString *)property; // JS中是否有這個對象 @property (readonly) BOOL isUndefined; // 比較兩個JS對象是否相等 - (BOOL)isEqualToObject:(id)value; // 調用者JSValue對象為JS中的方法名稱,arguments為參數,調用JS中Window直接調用的方法 - (JSValue *)callWithArguments:(NSArray *)arguments; // 調用者JSValue對象為JS中的全局對象名稱,method為全局對象的方法名稱,arguments為參數 - (JSValue *)invokeMethod:(NSString *)method withArguments:(NSArray *)arguments; // JS中的結構體類型轉換為OC + (JSValue *)valueWithPoint:(CGPoint)point inContext:(JSContext *)context;JSExport --- JS調用OC中的方法和屬性寫在繼承自JSExport的協議當中,OC對象實現自定義的協議 // textFunction -- JS方法 // - (void) ocTestFunction:(NSNumber *)value sec:(NSNumber *)number -- OC方法 JSExportAs (textFunction,- (void) ocTestFunction:(NSNumber *)value sec:(NSNumber *)number);

JSManagedValue --- JS和OC對象的內存管理輔助對象,主要用來保存JSValue對象,解決OC對象中存儲js的值,導致的循環引用問題

JSManagedValue *_jsManagedValue = [JSManagedValue managedValueWithValue:jsValue];[_context.virtualMachine addManagedReference:_jsManagedValue];

JSManagedValue本身只弱引用js值,需要調用JSVirtualMachine的addManagedReference:withOwner:把它添加到JSVirtualMachine中,這樣如果JavaScript能夠找到該JSValue的Objective-C owner,該JSValue的引用就不會被釋放。

JSVirtualMachine --- JS運行的虛擬機,有獨立的堆空間和垃圾回收機制,運行在不同虛擬機環境的JSContext可以通過此類通信。

Native Code 和 JS 之間的互相調用(以UIWebView中的JS為例)

JS中,點擊事件直接調用方法方式JS和Native代碼的互調如下:

1.1 JS代碼如下

<html> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport"><body> <script type="text/javascript"> var nativeCallJS = function(parameter) { alert (parameter); }; </script> <button type="button" onclick = "jsCallNative('jsparameter')" style="width:100%; height:30px;"/>調用OC代碼</button></body></html>

1.2 OC代碼如下

- (void)__jsLogic { self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception){ NSLog(@"JS代碼執行中的異常信息%@", exception); }; self.jsContext = [self valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.jsContext[@"jsCallNative"] = ^(NSString *paramer){ JSValue *currentThis = [JSContext currentThis]; JSValue *currentCallee = [JSContext currentCallee]; NSArray *currentParamers = [JSContext currentArguments]; dispatch_async(dispatch_get_main_queue(), ^{ /** * js調起OC代碼,代碼在子線程,更新OC中的UI,需要回到主線程 */ }); NSLog(@"JS paramer is %@",paramer); NSLog(@"currentThis is %@",[currentThis toString]); NSLog(@"currentCallee is %@",[currentCallee toString]); NSLog(@"currentParamers is %@",currentParamers); }; JSValue *jsMethod = self.jsContext[@"nativeCallJS"]; [jsMethod callWithArguments:@[@"nativeCallJS"]]; }1.3 OC運行結果,彈出HTML中的alert提示 2016-08-05 17:57:08.974 LeWebViewPro[38150:3082770] JS paramer is jsParameter 2016-08-05 17:57:08.975 LeWebViewPro[38150:3082770] currentThis is [object Window] 2016-08-05 17:57:08.975 LeWebViewPro[38150:3082770] currentCallee is function () { [native code]} 2016-08-05 17:57:08.975 LeWebViewPro[38150:3082770] currentParamers is ( jsParameter )

JS中,點擊事件等事件通過調用全局對象的方法調用方法,JS和Native代碼的互調如下:

2.1 JS代碼如下

<html> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport"> <body> <script type="text/javascript"> globalObject = new Object(); globalObject.name = 100; globalObject.nativeCallJS = function (parameter) { alert (parameter); }; </script> <button type="button" onclick = "globalObject.jsCallNative('jsParameter')" style="width:100%; height:30px;"/>調用OC代碼</button> </body> </html>2.2 OC代碼如下

2.2.1 JSManager 代碼,負責執行JS中的方法

#import <JavaScriptCore/JavaScriptCore.h>#import <Foundation/Foundation.h>@protocol LeJSExport <JSExport>JSExportAs (jsCallNative,- (void) jsCallNative:(NSString *)jsParameter);@end@interface JSManager : NSObject<LeJSExport>@end-----.M文件-----#import "JSManager.h"@implementation JSManager- (void)jsCallNative:(NSString *)jsParameter{ JSValue *currentThis = [JSContext currentThis]; JSValue *currentCallee = [JSContext currentCallee]; NSArray *currentParamers = [JSContext currentArguments]; dispatch_async(dispatch_get_main_queue(), ^{ /** * js調起OC代碼,代碼在子線程,更新OC中的UI,需要回到主線程 */ }); NSLog(@"JS paramer is %@",jsParameter); NSLog(@"currentThis is %@",[currentThis toString]); NSLog(@"currentCallee is %@",[currentCallee toString]); NSLog(@"currentParamers is %@",currentParamers);}@end

2.2.2 包含UIWebView類的代碼,負責調起JS中的方法

- (void)nativeCallJS{ self.jsManager = [[JSManager alloc] init]; self.jsContext = [self valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception){ NSLog(@"JS代碼執行中的異常信息%@", exception); }; self.jsContext[@"globalObject"] = self.jsManager; //1.OC方法調起JS JSValue *varibleStyle = self.jsContext[@"globalObject"]; [varibleStyle invokeMethod:@"nativeCallJS" withArguments:@[@100]]; //2.OC腳本調起JS NSString *jsScript = [NSString stringWithFormat:@"globalObject.nativeCallJS('%@')",@100]; [self.jsContext evaluateScript:jsScript];}

2.3 OC運行結果,彈出HTML中的alert提示

2016-08-07 10:30:11.444 LeWebViewPro[46674:3253852] JS paramer is jsParameter 2016-08-07 10:30:11.444 LeWebViewPro[46674:3253852] currentThis is [object JSManager] 2016-08-07 10:30:11.444 LeWebViewPro[46674:3253852] currentCallee is function () { [native code] } 2016-08-07 10:30:11.445 LeWebViewPro[46674:3253852] currentParamers is ( jsParameter )

JavaScriptCore和UIWebView的使用的注意事項

OC在與UIWebView中的JS交互的邏輯是,先獲取UIWebView中的JS的執行環境 self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];獲取UIWebView中的JS的執行環境的時機,一般在webViewDidFinishLoad時獲取,獲取不到的情況下,需改在其他方法中獲取shouldStartLoadWithRequest:Sent before a web view begins loading a framewebViewDidStartLoad:Sent after a web view starts loading a frame.webViewDidFinishLoad:Sent after a web view finishes loading a frame

線程問題

JavaScriptCore中提供的API都是線程安全的,一個JSVirtualMachine在一個線程中,它可以包含多個JSContext,而且相互之間可以傳值,為了確保線程安全,這些context在運行的時候會采用鎖,可以認為是串行執行。JS調用OC的回調方法,是在子線程,所以需要更新OC中的UI的話,需要切換到主線程

內存問題

oc中使用ARC方式管理內存(基于引用計數),但JavaScriptCore中使用的是垃圾回收方式,其中所有的引用都是強引用,但是我們不必擔心其循環引用,js的垃圾回收能夠打破這些強引用,有些情況需要考慮如下

js調起OC回調的block中獲取JSConetxt容易循環引用

self.jsContext[@"jsCallNative"] = ^(NSString *paramer){ // 會引起循環引用 JSValue *value1 = [JSValue valueWithNewObjectInContext: self.jsContext]; // 不會引起循環引用 JSValue *value = [JSValue valueWithNewObjectInContext: [JSContext currentContext]];};

JavaScriptCore中所有的引用都是強引用,所以在OC中需要存儲JS中的值的時候,需要注意

在oc中為了打破循環引用我們采用weak的方式,不過在JavaScriptCore中我們采用內存管理輔助對象JSManagedValue的方式,它能幫助引用技術和垃圾回收這兩種內存管理機制之間進行正確的轉換

JavaScriptCore單獨使用

js代碼如下test.jsglobalObject = new Object();globalObject.name = 100;globalObject.nativeCallJS = function (parameter) { alert (parameter);};

OC讀取JS文件,并相互通信

NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"js"]; NSString *jsContent = [[NSString alloc] initWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:nil]; JSContext *jsContext = [[JSContext alloc] init]; //捕獲運行js腳本的錯誤信息 jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { context.exception = exceptionValue; NSLog(@"異常信息:%@", exceptionValue); }; //js腳本添加到當前的js執行環境中 [jsContext evaluateScript:jsContent]; self.jsManager = [[JSManager alloc] init]; jsContext[@"globalObject"] = self.jsManager; ... ...

jS與OC的交互與通過UIWebView相同

相關博客

JavaScript和Objective-C交互的那些事

說說JavaScriptCore


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 911网站大全在线观看 | 国产一区视频观看 | 老女人碰碰在线碰碰视频 | 免费毛片儿 | 久久福利精品 | 国产美女爽到喷白浆的 | 成人在线视频免费看 | 性生活香蕉视频 | 黄色av网站免费 | 一级电影免费看 | 免费看真人a一级毛片 | 日本黄色大片免费 | 最新se94se在线欧美 | 蜜桃视频在线观看免费 | 91青青 | 国产免费一区二区三区网站免费 | 高清av在线 | 狠狠操人人干 | 91久久久久久久一区二区 | 在线观看免费污视频 | 国产精品99久久久久久大便 | 蜜桃视频在线免费观看 | 国产羞羞视频在线观看免费应用 | 免费看成年人视频在线 | 亚洲精品xxx | 亚洲欧美成aⅴ人在线观看 免费看欧美黑人毛片 | aaaaaaa毛片| 国产不卡av在线 | 久久久久久久久久久高潮一区二区 | 91精品国产免费久久 | 亚洲精品久久久久久久久久 | 亚洲字幕av | 午夜精品毛片 | 亚洲看片网 | 成人区一区二区三区 | 爱视频福利 | 国产羞羞视频在线观看 | 黄色电影免费提供 | 全黄性色大片 | 国产羞羞视频 | 免费人成在线观看网站 |