【问题标题】:WebScriptObject pass NSDictionary (associative array / object)WebScriptObject 传递 NSDictionary(关联数组/对象)
【发布时间】:2015-01-13 23:23:49
【问题描述】:

我正在使用 WebScriptObject 在 Objective-C (OS X) 的 WebView 中调用 JavaScript 方法。我想发送和接收像数组和字典这样的对象。

我可以这样接收它们:

// 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"];

然后当我像 window.external.log({key: "value"}); 这样进行 JavaScript 调用时,我的 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 对象。我能找到的一小部分文档(我在这里没有再次找到它以供参考)告诉我它只适用于数组。

我向苹果提交了错误报告:19464522

为什么 Objective-C API 提供了将所有内容转换为对象形式 JavaScript 的方法,但反之却没有?!

一定有可能,那我该如何实现呢?

【问题讨论】:

    标签: javascript objective-c webview nsdictionary web-scripting


    【解决方案1】:

    我也一直在摸索解决此限制的最佳方法,尝试了一些基于类的实现但没有取得多大成功,最终找到了一种解决方法,归结为:

    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" })]];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-23
      • 2018-01-17
      • 1970-01-01
      • 2012-08-30
      • 2011-02-02
      • 2017-12-01
      • 1970-01-01
      相关资源
      最近更新 更多