NSDictionary快速KVC,零值

时间:2013-12-24 11:10:54

标签: ios objective-c json nsarray nsdictionary

不确定我是否正确命名了问题,但这里是:

假设我从API返回了JSON响应。使用SBJson解析JSON,它可以完美运行。 JSON的一个例子:

{
    "value": 15199,          //this field is required
    "value_str": "$1.5k",    //this field is required
    "change": 33             //this field is optional
}

现在这可以在一个整洁的小NSDictionary中解析,我可以从中阅读。到目前为止,我有这样的想法:

//lets assume that "dict" is the parsed JSON using SBJSON
NSDictionary *number = @{@"value_str": [dict objectForKey:@"value_str"]}; //this works
number = @{@"value_str": [dict objectForKey:@"value_str"], @"change": [dict objectForKey:@"change"]}; //this crashes if there was no "change" in JSON

因此我发生崩溃是因为我试图将nil值设置为NSDictionary的对象,这是不允许的。如果change字段始终存在,这将起作用。如何解决这个问题? 我真的必须这样做:

NSDictionary *number = [NSDictionary dictionary];
[number setValue:[dict objectForKey:@"value_str"] forKey:@"value_str"];
[number setValue:[dict objectForKey:@"change"] forKey:@"change"];
对于dict中的每个键值对,

等等?这写起来要慢得多,也很痛苦。必须有更好的方法,对吗?请? :)

哦,如果我设置setValue ForKey然后查询objectForKey,我会得到我用setValue ForKey设置的对象(或值)吗?

编辑:我有个主意,但我不确定如何有效地实施它。而不是在这里检查每个键等等,为什么不继承NSDictionary并覆盖我@{}的{​​{1}}构造函数。我熟悉编译器dictionaryWithObjectsAndKeys,但我没有足够的知识来有效地实现这样的构造函数。如果有人这样做,那就太棒了。 整个想法是检查该构造函数方法中的值,如果对象是va_list,则只需跳过它。怎么样?有人可以打勾或者这是个坏主意吗? EDIT2:发现子类化是个坏主意:)使用了评论中提供的解决方案。

2 个答案:

答案 0 :(得分:3)

关于第一个问题我认为最好的协议是每次检查价值,或者复制字典。

关于第二个问题:

objectForKey:接受任何对象作为键,而不仅仅是字符串。唯一的要求是密钥支持NSCopying协议。

另一个区别是,如果你给setValue:forKey:一个nil值,它会从字典中删除密钥(如果它存在),否则什么也不做。但是如果你给setObject:forKey:一个零值,它会引发异常。

执行valueForKey:时,您需要为其NSString,而objectForKey:可以将任何NSObject子类作为键。这是因为对于键值编码,键始终是字符串。

事实上,文档指出即使你给valueForKey:一个NSString,它也会调用objectForKey:,除非字符串以@开头,在这种情况下它调用{{} 1}},可能会调用[super valueForKey:],这可能会引发异常。

答案 1 :(得分:1)

 NSArray *keysArray=[[NSArray alloc]initWithObjects:@"value",@"value_str",@"change", nil];

NSDictionary *dict =[[NSDictionary alloc]init]; // your service response dict
NSMutableDictionary *savedict =[[NSMutableDictionary alloc]init]; // finally saved dict

for (int i=0; i<[[dict objectForKey:@"your parentkey here"] count]; i++) {

    if ([dict objectForKey:keysArray[i]]) {
        [savedict setObject:[dict objectForKey:keysArray[i]] forKey:keysArray[i]];
    }
    else
    {
        [savedict setObject:@"" forKey:keysArray[i]];

    }
}