具有 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_lists,但我没有足够的知识来有效地实现这样的构造函数。如果有人会这样做,那就太棒了。 整个想法是检查该构造方法中的值,如果对象是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的主要内容,如果未能解决你的问题,请参考以下文章

使用具有多个值的键创建 NSDictionary

从 NSDictionary 数组中获取具有值的数组

两个 NSArray 组合成一个具有交替值的 NSDictionary

复制没有空值的 NSDictionary?

NSdictionary 到 JSON 数据正在排序

添加具有 nil 值的新动态属性