天天看點

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

六、Objective-C與JavaScript複雜對象的映射

   我們在使用JavaScript調用Objective-C方法的實質是将一個OC函數設定為了JS全局對象的一個屬性,當然我們也可以設定非函數的屬性或者任意JSValue(或者可以轉換為JSValue)的值。例如:

   self.jsContext = [[JSContext alloc]init];

   //向JS全局對象中添加一個擷取目前Native裝置類型的屬性

   [self.jsContext setObject:@"iOS" forKeyedSubscript:@"deviceType"];

但是如果我們想把OC自定義的一個類的對象設定為JS全局對象的某個屬性,JS和OC有着完全不同的對象原理,如果不做任何處理,JS是接收不到OC對象中定義的屬性和方法的。這時就需要使用到前面提到的JSExport協定,需要注意,這個協定不是用來被類遵守的,它裡面沒有規定任何方法,其是用來被繼承定義新的協定的,自定義的協定中約定的方法和屬性可以在JS中被擷取到,示例如下:

OC中建立一個自定義的類:

@protocol MyObjectProtocol <JSExport>

@property(nonatomic,strong)NSString * name;

@property(nonatomic,strong)NSString * subject;

@property(nonatomic,assign)NSInteger age;

-(void)sayHi;

@end

@interface MyObject : NSObject<MyObjectProtocol>

@implementation MyObject

-(void)sayHi{

   NSLog(@"Hello JavaScript");

}

添加到JS全局對象中:

   MyObject* object = [MyObject new];

   object.name = @"Jaki";

   object.age = 25;

   object.subject = @"OC";

   [jsContext setObject:object forKeyedSubscript:@"deviceObject"];

在JS運作環境中可以完整的到deviceObject對象,如下:

七、C語言風格的API解釋

   JavaScriptCore架構中除了包含完整的Objective-C和Swift語言的API外,也提供了對C語言的支援。

   與JS運作環境相關的方法如下:

//建立一個JSContextRef組

/*

JSContextRef相當于JSContext,同一組中的資料可以共享

*/

JSContextGroupRef JSContextGroupCreate(void);

//記憶體引用

JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group);

//記憶體引用釋放

void JSContextGroupRelease(JSContextGroupRef group);

//建立一個全局的運作環境

JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass);

//同上

JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass);

JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx);

void JSGlobalContextRelease(JSGlobalContextRef ctx);

//擷取全局對象

JSObjectRef JSContextGetGlobalObject(JSContextRef ctx);

//擷取JSContextRef組

JSContextGroupRef JSContextGetGroup(JSContextRef ctx);

//擷取全局的運作環境

JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx);

//擷取運作環境名

JSStringRef JSGlobalContextCopyName(JSGlobalContextRef ctx);

//設定運作環境名

void JSGlobalContextSetName(JSGlobalContextRef ctx, JSStringRef name);

   與定義JS對象的相關方法如下:

//定義JS類

參數JSClassDefinition是一個結構體 其中可以定義許多回調

JSClassRef JSClassCreate(const JSClassDefinition* definition);

//引用記憶體

JSClassRef JSClassRetain(JSClassRef jsClass);

//釋放記憶體

void JSClassRelease(JSClassRef jsClass);

//建立一個JS對象

JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data);

//定義JS函數

JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction);

//定義構造函數

JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor);

//定義數組

JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);

//定義日期對象

JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);

//定義異常對象

JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);

//定義正則對象

JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);

//定義函數對象

JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception);

//擷取對象的屬性

JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object);

//設定對象的屬性

void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value);

//檢查對象是否包含某個屬性

bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);

//擷取對象屬性

JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);

//定義對象屬性

void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception);

//删除對象屬性

bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);

//擷取數組值

JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception);

//設定數組值

void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception);

//擷取私有資料

void* JSObjectGetPrivate(JSObjectRef object);

//設定私有資料

bool JSObjectSetPrivate(JSObjectRef object, void* data);

//判斷是否為函數

bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object);

//将對象作為函數來調用

JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);

//判斷是否為構造函數

bool JSObjectIsConstructor(JSContextRef ctx, JSObjectRef object);

//将對象作為構造函數來調用

JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);

//擷取所有屬性名

JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object);

//進行記憶體引用

JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array);

//記憶體釋放

void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array);

//擷取屬性個數

size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array);

//在屬性名數組中取值

JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index);

//添加屬性名

void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef accumulator, JSStringRef propertyName);

   JS資料類型相關定義在JSValueRef中,如下:

//擷取值的類型

枚舉如下:

typedef enum {

   kJSTypeUndefined,

   kJSTypeNull,

   kJSTypeBoolean,

   kJSTypeNumber,

   kJSTypeString,

   kJSTypeObject

} JSType;

JSType JSValueGetType(JSContextRef ctx, JSValueRef);

//判斷是否為undefined類型

bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value);

//判斷是否為null類型

bool JSValueIsNull(JSContextRef ctx, JSValueRef value);

//判斷是否為布爾類型

bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value);

//判斷是否為數值類型

bool JSValueIsNumber(JSContextRef ctx, JSValueRef value);

//判斷是否為字元串類型

bool JSValueIsString(JSContextRef ctx, JSValueRef value);

//判斷是否為對象類型

bool JSValueIsObject(JSContextRef ctx, JSValueRef value);

//是否是類

bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass);

//是否是數組

bool JSValueIsArray(JSContextRef ctx, JSValueRef value);

//是否是日期

bool JSValueIsDate(JSContextRef ctx, JSValueRef value);

//比較值是否相等

bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception);

//比較值是否全等

bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b);

//是否是某個類的執行個體

bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception);

//建立undefined值

JSValueRef JSValueMakeUndefined(JSContextRef ctx);

//建立null值

JSValueRef JSValueMakeNull(JSContextRef ctx);

//建立布爾值

JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool boolean);

//建立數值

JSValueRef JSValueMakeNumber(JSContextRef ctx, double number);

//建立字元串值

JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string);

//通過JSON建立對象

JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string);

//将對象轉為JSON字元串

JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef value, unsigned indent, JSValueRef* exception);

//進行布爾值轉換

bool JSValueToBoolean(JSContextRef ctx, JSValueRef value);

//進行數值轉換

double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception);

//字元串值指派

JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception);

//值與對象的轉換

JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception);

   在C風格的API中,字元串也被包裝成了JSStringRef類型,其中方法如下:

//建立js字元串

JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars);

JSStringRef JSStringCreateWithUTF8CString(const char* string);

//記憶體引用于釋放

JSStringRef JSStringRetain(JSStringRef string);

void JSStringRelease(JSStringRef string);

//擷取字元串長度

size_t JSStringGetLength(JSStringRef string);

//轉成UTF8字元串

size_t JSStringGetUTF8CString(JSStringRef string, char* buffer, size_t bufferSize);

//字元串比較

bool JSStringIsEqual(JSStringRef a, JSStringRef b);

bool JSStringIsEqualToUTF8CString(JSStringRef a, const char* b);

繼續閱讀