具有 nil 值的 NSDictionary 快速 KVC
Posted
技术标签:
【中文标题】具有 nil 值的 NSDictionary 快速 KVC【英文标题】:NSDictionary fast KVC with nil values 【发布时间】:2013-12-24 11:10:53 【问题描述】:不确定我是否正确命名了这个问题,但这里是:
假设我有一个从 API 返回的 JSON 响应。 JSON 使用 SBJson
解析,完美无瑕。 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"];
对于字典中的每个键值对等等?这样写起来更慢更痛苦。必须有更好的方法,对吧?请? :)
哦,如果我设置setValue ForKey
,然后像objectForKey
这样查询,我会得到我用setValue ForKey
设置的对象(或值)吗?
编辑:我有一个想法,但我不确定如何有效地实施它。而不是在这里检查每个键等等为什么不继承NSDictionary
并覆盖@
构造函数,我认为它是dictionaryWithObjectsAndKeys
。我熟悉编译器va_list
s,但我没有足够的知识来有效地实现这样的构造函数。如果有人会这样做,那就太棒了。
整个想法是检查该构造方法中的值,如果对象是nil
,则跳过它。怎么样?有人可以让它打勾还是一个坏主意?EDIT2:发现子类化是一个坏主意:) 使用了 cmets 中提供的解决方案。
【问题讨论】:
为什么不写一个foreach循环来迭代json中所有key的值? 因为可以说我并不总是需要“值”,而且如果字典有 100 个条目,那将是非常低效的。 我认为您需要检查每次是否存在关键“更改”。如果是,则提取该键值,否则不提取它。我现在只能看到这种方式。 将对象从一本字典转录到另一本有什么意义?为什么不复制字典,或者使用相同的字典对象? +1 回答这个问题。我见过的最好的解决方法是@@"key": keyValue ? : [NSNull null]
。这将添加keyValue
,如果不是nil
,或者null
,如果nil
。
【参考方案1】:
关于第一个问题,我认为最好的办法是每次检查值,或者复制字典。
关于第二个问题:
objectForKey:
接受任何对象作为键,而不仅仅是字符串。唯一的要求是密钥支持NSCopying
协议。
另一个区别是如果你给setValue:forKey:
一个nil值,如果它存在的话,它会从字典中删除,否则什么都不做。但是如果你给 setObject:forKey:
一个 nil 值,它会引发一个异常。
当您执行valueForKey:
时,您需要给它一个NSString
,而objectForKey:
可以将任何NSObject
子类作为键。这是因为对于键值编码,键始终是字符串。
事实上,文档指出,即使你给valueForKey:
一个NSString
,它仍然会调用objectForKey:
,除非字符串以@ 开头,在这种情况下它会调用[super valueForKey:]
,这可能会调用@ 987654334@ 可能会引发异常。
【讨论】:
第二部分说清楚了,但我在将 nil 值插入 NSDictionary 部分之后。有一个想法来继承它。检查已编辑的问题。 真的我认为继承 nsdictionary 是个坏主意。检查子类化注释。 developer.apple.com/library/mac/documentation/Cocoa/Reference/… 。 @guilherme 提供了很好的解决方法:@@"key": keyValue ? : [NSNull null]【参考方案2】: 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]];
【讨论】:
是的,这确实是一种方式,但是当我遇到很多像上面描述的情况(有更多可选属性和更多格式)时,它变得非常不切实际。您的解决方案确实有效,但我正在寻找更简洁的解决方案。以上是关于具有 nil 值的 NSDictionary 快速 KVC的主要内容,如果未能解决你的问题,请参考以下文章