【问题标题】:NSDictionary objectForKey return valueNSDictionary objectForKey 返回值
【发布时间】: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。

【问题讨论】:

    标签: objective-c json parsing nsarray nsdictionary


    【解决方案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"];
    

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

    【讨论】:

    【解决方案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。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    相关资源
    最近更新 更多