NSDictionary objectForKey 返回值

Posted

技术标签:

【中文标题】NSDictionary objectForKey 返回值【英文标题】:NSDictionary objectForKey return value 【发布时间】:2009-06-22 03:40:14 【问题描述】:

我正在使用 json-framework 从 JSON 响应中创建一个 NSDictionary。这么多效果很好。

现在,在这个 JSON 负载中有一个或多个对象 - 我们称它们为 X。在 XML 中有点像这样:

<OBJECTS>
  <X>
    ...
  </x>
  <X>
    ...
  </X>
  <X>
    ...
  </X>
</OBJECTS>

当我在上述 NSDictionary 对象中查找所有 X 时,如下所示:

NSDictionary *results = [[dict objectForKey:@"OBJECTS"] objectForKey:@"X"];

甚至:

NSDictionary *results = [dict valueForKeyPath:@"OBJECTS.X"];

根据 gdb,我得到了一个由 NSDictionary 对象组成的 NSCFArray。 (是的,我在这里也闻到了一些有趣的东西,但稍后会详细介绍。)

当只有 一个 对象名为 X 时,我会返回一个诚实的 NSDictionary。

那么...我应该怎么做才能使其行为一致,无论有多少个 X?

乍一看,我认为我只是将结果更改为 NSArray *,但是当我想快速枚举结果时会发生什么?现在我这样做:

for (NSDictionary *result in results)

在 NSCFArray 的情况下(多个 X),我为每个 X 返回一个单独的 NSDictionary。在单个 X 的情况下,我返回一个 NSDictionary,但现在我的观点太深了一层。换句话说,而不是这个(人为的例子):

(gdb) po results
<NSCFArray 0xd4a940>(

    foo =     
        bar = "something";
    ;


    foo =     
        bar = "something else";
    ;

)

我明白了:

(gdb) po results

    foo =     
        bar = "something";
    ;

欢迎/赞赏线索!您甚至可能会问是否有必要将其分开,但现在让我们假设这次旅行确实是必要的。 (不过,如果有人对此感到足够强烈,我很高兴被说服。)

最终,在一天结束时,我想要一个由 NSDictionary 对象组成的 NSArray。

【问题讨论】:

【参考方案1】:

我不熟悉 JSON 或 json 框架,但显然 objectForKey 不能用于访问 X,因为它们都有相同的密钥。

如果您知道 objectForKey:@"OBJECTS" 将返回 NSDictionary(单个元素)或 NSDictionarys(多个 X 元素)的 NSArray,那么您可以执行以下操作:

if ( ![results isKindOfClass:[NSArray class]] ) 
    results =[NSArray arrayWithObject:results];

假设您完全了解 json 框架的行为方式,这将为您提供一致的结果。它会有些脆弱,如果元素返回一个条目数组而不是 NSDitionary,那么它就会崩溃。

json-framework 可能有一个配置设置,可让您控制它在这种情况下的行为方式,这将是可取的。

【讨论】:

啊,我没有意识到 objectForKey 不能用于访问同一个键的多个实例 - 谢谢! (虽然它似乎与 NSCFArray 完全一样......或者我产生了幻觉......或者它只是未定义的行为,我很幸运。)我刚刚看到这篇文章,它处理多个 X 的情况,事实上,所以我接下来要试一试。如果它有效,我将总结修复并在这里报告! iphonedevelopertips.com/cocoa/… 同时,这是我正在使用的成员函数。请注意,它返回一个字典或数组。除非有任何库模块,否则如果我可以测试字典,我可以在必要时将它分配给一个单对象数组。 json-framework.googlecode.com/svn/trunk/documentation/… 关于同一个键的多个实例我错了。 (当然,我的意思是,如果 NSDictionary 是这样工作的,那么它就是这样工作的!)事实证明,我们确实有一系列字典,这正是你所猜测的。 :) 这个答案在其他问题上帮助了我!非常感谢【参考方案2】:
NSDictionary *results = [[dict objectForKey:@"OBJECTS"] objectForKey:@"X"];

NSDictionary *results = [dict valueForKeyPath:@"OBJECTS.X"];

以上两个是完全一样的。第一个操作比第二个操作成本更高。

【讨论】:

使用 CLANG 编译时,您还可以使用 Objective-c 文字 dict[@"OBJECTS"] - clang.llvm.org/docs/ObjectiveCLiterals.html【参考方案3】:

这是我最终做的:

// Get the JSON response and return the result:
NSString *jsonString = [NSString stringWithContentsOfURL:url];
NSDictionary *dict = [jsonString JSONValue];

// If OBJECTS.X gets a dictionary (one value), make an array of one.
id myObject = [dict valueForKeyPath:@"OBJECTS.X"];
if ([myObject isKindOfClass:[NSDictionary class]]) 
    results = [NSArray arrayWithObject:myObject];
 else 
    results = myObject;

值得指出的是,JSONValue 也可以返回一个字典一个数组。但是,我正在查找字典后分配 (OBJECTS.X)。

【讨论】:

在我们讨论的同时,还值得指出的是,Peter 的建议更简洁!我们知道我们要返回一个字典或数组,所以在 Peter 的例子中,如果它不是一个数组,它就是一个字典,我们可以从中创建一个单对象数组。【参考方案4】:

我不认为你的两个代码示例,

NSDictionary *results = [[dict objectForKey:@"OBJECTS"] objectForKey:@"X"];

NSDictionary *results = [dict valueForKeyPath:@"OBJECTS.X"];

是等价的。 Key-Value-Coding 有一些额外的智能来处理集合,这可能会让你失望。 (可以在 Scott Stevenson 的博客文章 Theocacao: NSArray and KVC 中找到一个示例。) 如果您恢复到前者,您可能会得到您期望的行为。

【讨论】:

谢谢!在这种特殊情况下,“po results”对这两个代码示例显示完全相同的内容。 (Scout 的荣誉!)由于在给定字典中不能有多个“X”,因此在这种情况下,每个“X”都是它自己的 NSDictionary 对象。但是......可能还有另一个原因不使用 valueForKeyPath:。 :-o belkadan.com/blog/2007/10/… 我应该澄清一下:如果我查看关键对象的对象,我会得到一个字典。如果我在那里查找键 X,that 最终会成为字典数组,因为原始 XML/JSON 中有多个 X。

以上是关于NSDictionary objectForKey 返回值的主要内容,如果未能解决你的问题,请参考以下文章

NSDictionary objectForKey 随机回答

NSDictionary objectForKey 运行时错误的 stringValue

使用 objectForKey 返回错误类型的键

十二:objectForKey与valueForKey区别简单分析

Swift 从 NSDictionary 读取数据

NSDictionary全部API的学习。