WebScriptObject 传递 NSDictionary(关联数组/对象)

Posted

技术标签:

【中文标题】WebScriptObject 传递 NSDictionary(关联数组/对象)【英文标题】:WebScriptObject pass NSDictionary (associative array / object) 【发布时间】: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 的方法,但反之却没有?!

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

【问题讨论】:

【参考方案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" )]];

【讨论】:

以上是关于WebScriptObject 传递 NSDictionary(关联数组/对象)的主要内容,如果未能解决你的问题,请参考以下文章

iOS登录模式

下载时确定文件大小

Plist 没有在 Objective C 中创建

应用程序在后台时不显示推送通知

如何按数值对包含 NSDictionary 的 NSMutableArray 进行排序?

当应用程序未运行时处理 JSON 推送通知解析