天天看點

讓你的iOS應用程式支援運作JavaScript腳本:JavaScriptCore架構詳解(二)

四、深入JSContext類

   看到這,你已經學會最基礎的OC與JS互相問好(互動)。下面我們再來深入看下JSContext中的屬性和方法。

   建立JSContext對象有如下兩種方式:

//建立一個新的JS運作環境

- (instancetype)init;

//建立一個新的JS運作環境 并關聯到某個虛拟機對象上

- (instancetype)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;

   執行JS代碼有如下兩個方法:

//執行JS代碼 結果将封裝成JSValue對象傳回

- (JSValue *)evaluateScript:(NSString *)script;

//作用同上

- (JSValue *)evaluateScript:(NSString *)script withSourceURL:(NSURL *)sourceURL NS_AVAILABLE(10_10, 8_0);

   下面的屬性和方法可以擷取到JS運作環境中的一些資訊:

//目前的JS運作環境 當JS調用OC方法時,在OC方法中可以用此方法擷取到JS運作環境

+ (JSContext *)currentContext;

//擷取目前執行的JS函數,當JS調用OC方法時,在OC方法中可以用此方法擷取到執行的函數

+ (JSValue *)currentCallee;

//擷取目前執行的JS函數中的this指向的對象

+ (JSValue *)currentThis;

//擷取目前執行函數的參數清單,當JS調用OC方法時,在OC方法中可以用此方法擷取到執行的函數的參數清單

+ (NSArray *)currentArguments;

//擷取目前JS運作環境的全局對象

@property (readonly, strong) JSValue *globalObject;

//當運作的JavaScript代碼抛出了未捕獲的異常時,這個屬性會被指派為抛出的異常

@property (strong) JSValue *exception;

//設定為一個異常捕獲的block,如果異常被此block捕獲,exception屬性就不再被指派了

@property (copy) void(^exceptionHandler)(JSContext *context, JSValue *exception);

//目前運作環境所關聯的虛拟機

@property (readonly, strong) JSVirtualMachine *virtualMachine;

//目前運作環境名稱

@property (copy) NSString *name;

//擷取目前JS運作環境全局對象上的某個屬性

- (JSValue *)objectForKeyedSubscript:(id)key;

//設定目前JS運作環境全局對象上的屬性

- (void)setObject:(id)object forKeyedSubscript:(NSObject <NSCopying> *)key;

//将C語言環境的JS運作環境轉換為OC環境的JS運作環境

+ (JSContext *)contextWithJSGlobalContextRef:(JSGlobalContextRef)jsGlobalContextRef;

//C語言環境的JS運作上下文

@property (readonly) JSGlobalContextRef JSGlobalContextRef;

五、深入JSValue類

   JSValue是JavaScript與Objective-C之間的資料橋梁。在Objective-C中調用JS腳本或者JS調用OC方法都可以使用JSValue來傳輸資料。其中屬性和方法示例如下:

//所對應的JS運作環境

@property (readonly, strong) JSContext *context;

//在指定的JS運作環境中建立一個JSValue對象

+ (JSValue *)valueWithObject:(id)value inContext:(JSContext *)context;

//建立布爾值

+ (JSValue *)valueWithBool:(BOOL)value inContext:(JSContext *)context;

//建立浮點值

+ (JSValue *)valueWithDouble:(double)value inContext:(JSContext *)context;

//建立32位整型值

+ (JSValue *)valueWithInt32:(int32_t)value inContext:(JSContext *)context;

//建立32位無符号整形值

+ (JSValue *)valueWithUInt32:(uint32_t)value inContext:(JSContext *)context;

//建立空的JS對象

+ (JSValue *)valueWithNewObjectInContext:(JSContext *)context;

//建立空的JS數組

+ (JSValue *)valueWithNewArrayInContext:(JSContext *)context;

//建立JS正則對象

+ (JSValue *)valueWithNewRegularExpressionFromPattern:(NSString *)pattern flags:(NSString *)flags inContext:(JSContext *)context;

//建立JS錯誤資訊

+ (JSValue *)valueWithNewErrorFromMessage:(NSString *)message inContext:(JSContext *)context;

//建立JS null值

+ (JSValue *)valueWithNullInContext:(JSContext *)context;

//建立JS undefined值

+ (JSValue *)valueWithUndefinedInContext:(JSContext *)context;

JavaScript中的資料類型和Objective-C的資料類型還是有着很大的差異,其中對應關系如下:

Objective-C  JavaScript

nil undefined

NSNull null

NSString string

NSNumber number boolean

NSDictionary    Object

NSArray Array

NSDate Date  

Block Function

id Object

Class Object

下面這些方法可以将JSValue值轉換為Objective-C中的資料類型:

//将JSValue轉換為OC對象

- (id)toObject;

//将JSValue轉換成特定OC類的對象

- (id)toObjectOfClass:(Class)expectedClass;

//将JSValue轉換成布爾值

- (BOOL)toBool;

//将JSValue轉換成浮點值

- (double)toDouble;

//将JSValue轉換成32位整型值

- (int32_t)toInt32;

//将JSValue轉換成32位無符号整型值

- (uint32_t)toUInt32;

//将JSValue轉換成NSNumber值

- (NSNumber *)toNumber;

//将JSValue轉換成NSString值

- (NSString *)toString;

//将JSValue轉換成NSDate值

- (NSDate *)toDate;

//将JSValue轉換成NSArray值

- (NSArray *)toArray;

//将JSValue轉換成NSDictionary值

- (NSDictionary *)toDictionary;

//擷取JSValue對象中某個屬性的值

- (JSValue *)valueForProperty:(NSString *)property;

//設定JSValue對象中某個屬性的值

- (void)setValue:(id)value forProperty:(NSString *)property;

//删除JSValue對象中的某個屬性

- (BOOL)deleteProperty:(NSString *)property;

//判斷JSValue對象中是否包含某個屬性

- (BOOL)hasProperty:(NSString *)property;

//定義JSValue中的某個屬性 這個方法和JavaScript中Object構造函數的defineProperty方法一緻

/*

第2個參數設定此屬性的描述資訊 可以設定的鍵值如下:

NSString * const JSPropertyDescriptorWritableKey;//設定布爾值 是否可寫

NSString * const JSPropertyDescriptorEnumerableKey;//設定布爾值 是否可枚舉

NSString * const JSPropertyDescriptorConfigurableKey;//設定布爾值 是否可配置

NSString * const JSPropertyDescriptorValueKey;//設定此屬性的值

NSString * const JSPropertyDescriptorGetKey;//設定此屬性的get方法

NSString * const JSPropertyDescriptorSetKey;//設定此屬性的set方法

以上set、get方法的鍵和value、可寫性的鍵不能同時存在,其文法是JavaScript保持一緻

*/

- (void)defineProperty:(NSString *)property descriptor:(id)descriptor;

//擷取JS數組對象某個下标的值

- (JSValue *)valueAtIndex:(NSUInteger)index;

//設定JS數組對象某個下标的值

- (void)setValue:(id)value atIndex:(NSUInteger)index;

//判斷此對象是否為undefined

@property (readonly) BOOL isUndefined;

//判斷此對象是否為null

@property (readonly) BOOL isNull;

//判斷此對象是否為布爾值

@property (readonly) BOOL isBoolean;

//判斷此對象是否為數值

@property (readonly) BOOL isNumber;

//判斷此對象是否為字元串

@property (readonly) BOOL isString;

//判斷此對象是否為object對象

@property (readonly) BOOL isObject;

//判斷此對象是否為數組

@property (readonly) BOOL isArray;

//判斷此對象是否為日期對象

@property (readonly) BOOL isDate;

//比較兩個JSValue是否全相等 對應JavaScript中的===

- (BOOL)isEqualToObject:(id)value;

//比較兩個JSValue對象的值是否相等 對應JavaScript中的==

- (BOOL)isEqualWithTypeCoercionToObject:(id)value;

//判斷某個對象是否在目前對象的原型鍊上

- (BOOL)isInstanceOf:(id)value;

//如果JSValue是Function對象 可以調用此方法 和JavaScript中的call方法一緻

- (JSValue *)callWithArguments:(NSArray *)arguments;

//如果JSValue是一個構造方法對象 可以調用此方法 和JavaScript中使用new關鍵字一緻

- (JSValue *)constructWithArguments:(NSArray *)arguments;

//用此對象進行函數的調用 目前對象會被綁定到this中

- (JSValue *)invokeMethod:(NSString *)method withArguments:(NSArray *)arguments;

//将CGPoint轉換為JSValue對象

+ (JSValue *)valueWithPoint:(CGPoint)point inContext:(JSContext *)context;

//将NSRange轉換為JSValue對象

+ (JSValue *)valueWithRange:(NSRange)range inContext:(JSContext *)context;

//将CGRect轉換為JSValue對象

+ (JSValue *)valueWithRect:(CGRect)rect inContext:(JSContext *)context;

//将CGSize轉換為JSValue對象

+ (JSValue *)valueWithSize:(CGSize)size inContext:(JSContext *)context;

//轉換成CGPoint資料

- (CGPoint)toPoint;

//轉換成NSRange資料

- (NSRange)toRange;

//轉換成CGRect資料

- (CGRect)toRect;

//轉換為CGSize資料

- (CGSize)toSize;

//将C風格的JSValueRef對象轉換為JSValue對象

+ (JSValue *)valueWithJSValueRef:(JSValueRef)value inContext:(JSContext *)context;

其實在JavaScriptCore架構中還有一個JSManagerValue類,這個的主要作用是管理記憶體。雖然我們在編寫Objective-C代碼時有強大的自動引用技術(ARC技術),我們一般無需關心對象的記憶體問題,在編寫JavaScript代碼時也有強大的垃圾回收機制(這種機制下甚至連循環引用都不是問題),但是在OC和JS混合開發時,就很容易出現問題了,比如一個JS垃圾回收機制釋放掉的對象OC中卻還在用,反過來也是一樣。JSManagerValue對JSValue進行了一層包裝,它可以保證在适合時候使用這個對象時對象都不會被釋放,其中方法如下:

//建立JSVlaue對象的包裝JSManagerValue

+ (JSManagedValue *)managedValueWithValue:(JSValue *)value;

+ (JSManagedValue *)managedValueWithValue:(JSValue *)value andOwner:(id)owner;

- (instancetype)initWithValue:(JSValue *)value;

//擷取所包裝的JSValue對象

@property (readonly, strong) JSValue *value;