2015-01-13 106 views
2

我使用a WebScriptObject在Objective-C(OS X)中的WebView中調用JavaScript方法。我想發送和接收像數組和字典的對象。WebScriptObject傳遞NSDictionary(關聯數組/對象)

我可以接受他們這樣的:

// JWJSBridge 
+ (BOOL)isSelectorExpludedFromWebScript:(SEL)selector { 
    if (selector == @selector(log:)) { 
     return NO; 
    } 
    return YES; 
} 
+ (NSString *)webScriptNameForSelector:(SEL)selector { 
    if (selector == @selector(log:)) { 
     return @"log"; 
    } 
    return nil; 
} 
- (void)log:(WebScriptObject *)object { 
    NSLog(@"object: %@", [[object JSValue] toObject]); 
} 

該對象被設置爲JavaScript環境如下:

WebScriptObject *windowObject = [[self webView] windowScriptObject]; 
[windowObject setValue:[[JWJSBridge alloc] init] forKey:@"external"]; 

當我再作一個JavaScript調用,比如window.external.log({key: "value"});JWJSBridge記錄對象作爲NSDictionary

現在我也想實現它的另一種方式。對於我創建了一個JavaScript對象是這樣的:

window.internal = {log = function(a) { console.log(a); }}; 

它使用數組完美的作品:

WebScriptObject *internal = [[self webView] valueForKey:@"internal"]; 
[internal callWebScriptMethod:@"log" withArguments:@[@[@"value", @"value"]]]; 

但是,當我想送一本詞典,這是不可能的:

[internal callWebScriptMethod:@"log" withArgument:@[@{@"key": @"value"}]]; 

知道我不幸的是結束了一個空對象ObjCRuntimeObject控制檯消息。顯然,Objective C不能/不能將字典序列化爲JavaScript對象。我能找到的一小段文檔(我沒有再次找到它供參考)告訴我,它只適用於數組。

我申請到蘋果的bug報告:19464522

爲什麼Objective-C的API提供了轉向到一切形式的對象JavaScript方法而不是相反?

必須有一種可能性,那麼我該如何實現呢?

回答

0

被抓我的頭在最好的方式解決這個限制,以及,嘗試沒有成功幾類基於實現,並結束了與歸結爲一種解決方法:

id dict = [internal evaluateWebScript:@"(function() { return { key: { key: 'VALUE' } }; })()"]; 
[internal callWebScriptMethod:@"log" withArguments:@[dict]]; 

哪可以包裹起來這樣的(離開了錯誤處理爲了簡潔):

static id jsDictionary(WebScriptObject *const webScript, NSDictionary *const dictionary) 
{ 
    NSData *const data = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil]; 
    NSString *const json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
    return [webScript evaluateWebScript:[NSString stringWithFormat:@"(function() { return %@; })()", json]]; 
} 

然後使用這樣的:

[internal callWebScriptMethod:@"log" withArguments:@[jsDictionary(internal, @{ @"key": @"VALUE" })]];