2013-11-03 27 views
2

假設我有一個JavaScript文件javascript.js,其中包含以下內容。如何使用JavaScriptCore將JavaScript對象轉換爲NSDictionary

window.fruitsAndVeggies = { 
    name2CategoryMap: { 
     "apple": "fruit", 
     "carrot": "vegetable" 
    } 
} 

誰能告訴我獲得Javascript對象window.fruitsAndVeggies的內容到一個NSDictionary最簡單的方法?

來自互聯網上的各種來源,我將以下片段拼湊在一起,創建一個Javascript上下文,然後評估該上下文中的JavaScript代碼。

JSGlobalContextRef ctx = JSGlobalContextCreate(NULL); // create context 


JSValueRef exception = JSValueMakeUndefined(ctx); // create object to hold exceptions 

// Make a "window" object in the JS Context 
JSStringRef makeWindowScript = JSStringCreateWithUTF8CString("var window = {}"); 
JSValueRef result = JSEvaluateScript(ctx, makeWindowScript, NULL, NULL, 0, &exception); 


// load the javascript file into an NSString 
NSBundle *   bundle = [NSBundle bundleWithIdentifier:@"my.bundle"]; 
NSString *filePath = [bundle pathForResource:@"javascript" ofType:@"js"]; 

NSError *error; 
NSString *stringFromFile = [[NSString alloc] 
           initWithContentsOfFile:filePath 
           encoding:NSUTF8StringEncoding 
           error:&error]; 

// convert NSString to a JSStringRef 
CFStringRef cfString = (__bridge CFStringRef)stringFromFile; 
JSStringRef jsString = JSStringCreateWithCFString(cfString); 


// evaluate the javascript 
JSEvaluateScript(ctx, jsString, NULL, NULL, 0, &exception); 

我很困惑接下來該做什麼。我需要在我的objective-c代碼中使用fruitsAndVeggies.name2CategoryMap的內容。訪問它們的最簡單方法是什麼?有一個簡單的函數可以調用它們將它們加載到Objective-C字典中嗎?

非常感謝您的幫助。

回答

0

事情都變得簡單了很多,因爲在JavaScriptCore的新的Objective-C接口與iOS 7中引入對於一個介紹到這,看到WWDC 2013屆「集成的JavaScript進入蘋果的開發者網絡上的本地應用」會議:https://developer.apple.com/videos/wwdc/2013/?id=615

評估你的JavaScript資源文件後需要的代碼是:

JSContext *context = [JSContext contextWithJSGlobalContextRef:ctx]; 
    NSDictionary *fruitsAndVeggiesDict = [context[@"window"][@"fruitsAndVeggies"][@"name2CategoryMap"] toObject]; 

    NSLog(@"name2CategoryMap['apple'] = %@", fruitsAndVeggiesDict[@"apple"]); 
    NSLog(@"name2CategoryMap['carrot'] = %@", fruitsAndVeggiesDict[@"carrot"]); 
0

盡我所能,我找不出一個優雅的方式將window.fruitsAndVeggies轉換成字典。我能做的最好的是手動循環遍歷JavaScript對象,並逐個將每個鍵/值對添加到字典中。

代碼如下。被警告:這是醜陋的。如果你有一個更簡潔的解決方案,我全是耳朵!

/* Make the dictionary. */ 
NSMutableDictionary *fruitsAndVeggiesDict = [NSMutableDictionary dictionary]; 


/* In the JS context, create a variable called "keys". 
    Return the number of keys (keys.length). */ 
result = JSEvaluateScript(ctx, JSStringCreateWithUTF8CString("var keys = Object.keys(window.fruitsAndVeggies.name2CategoryMap); keys.length"), NULL, NULL, 0, &exception); 

double numKeys = JSValueToNumber(ctx, result, &exception); 


/* Iterate over the keys; convert each key/value into a pair of NSStrings. */ 
for(int i = 0; i < numKeys; i++){ 

    // get a key, save in keyStrNS 
    NSString *getKeyStr = [NSString stringWithFormat:@"keys[%d]", i]; 
    CFStringRef getKeyStrCF = (__bridge CFStringRef)getKeyStr; 
    JSStringRef getKeyStrJS = JSStringCreateWithCFString(getKeyStrCF); 

    JSValueRef key = JSEvaluateScript(ctx, getKeyStrJS, NULL, NULL, 0, &exception); 

    JSStringRef keyStrJS = JSValueToStringCopy(ctx, key, &exception); 
    NSString *keyStrNS = (NSString *)JSStringCopyCFString(kCFAllocatorDefault, keyStrJS); 


    // get a value, save in valueStrNS 
    NSString *getValueStr = [NSString stringWithFormat:@"window.fruitsAndVeggies.name2CategoryMap[\"%@\"]", keyStrNS]; 
    CFStringRef getValueStrCF = (__bridge CFStringRef)getValueStr; 
    JSStringRef getValueStrJS = JSStringCreateWithCFString(getValueStrCF); 

    JSValueRef value = JSEvaluateScript(ctx, getValueStrJS, NULL, NULL, 0, &exception); 

    JSStringRef valueStrJS = JSValueToStringCopy(ctx, value, &exception); 
    NSString *valueStrNS = (NSString *)JSStringCopyCFString(kCFAllocatorDefault, valueStrJS); 

    /* store the key and value in our dictionary */ 
    [fruitsAndVeggiesDict setObject: valueStrNS forKey: keyStrNS]; 

    /* and print them for good measure */ 
    NSLog(@"key %@ has value %@",keyStrNS,valueStrNS); 

} 

輸出:

key apple has value fruit 
key carrot has value vegetable 
相關問題