2013-11-03 29 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 
相关问题