不确定我是否正确命名了问题,但这里是:
假设我从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:发现子类化是个坏主意:)使用了评论中提供的解决方案。
答案 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]];
}
}