'-setValue:forKey:'更新NSMutableDictionary的字段时的异常

时间:2013-11-17 13:09:49

标签: ios iphone objective-c

我有两个名为“dict”和newdict的NSMutableDictionary对象。然后尝试将newdict分配给“myfield1”字段。但是,我正面临一个错误。

NSMutableDictionary *dict = @{ @"myfield1" : @{  @"subfield1" : @"mysubfield1" ,
                                           @"subfield2" : @"mysubfield2" },
                              @"myfield2": @"myfield2",
                              @"myfield3": @"myfield3"};
NSMutableDictionary *newdict =  @{  @"subfield1" : @"mynewsubfield1" ,
                                    @"subfield2" : @"mynewsubfield2" };

[dict setValue:newdict forKey:@"myfield1"];

错误:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', 
reason: '[<__NSDictionaryI 0x17db3bb0> setValue:forUndefinedKey:]: 
this class is not key value coding-compliant for the key loc.'

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

不要使用setValue:forKey:,因为这是KVC方法,而不是字典方法。使用setObject:forKey:。从技术上讲,KVC方法可行,但通常只有在有特殊需要时才能使用它。

您真正的问题是您的字典实例不可变。使用mutableCopy从文字定义创建可变版本。文字定义总是不可变的。

答案 1 :(得分:1)

正如@Wain所解释的那样,你的字典实例不可变。

您可能会感到困惑的是,您将变量声明为NSMutableDictionary,因此您认为它们是可变的。但 @{ … }字面语法等同于[NSDictionary dictionaryWithObjects:forKeys:count:,因此创建(不可变)NSDictionary实例

您将此值影响到NSMutableDictionary类型的变量的事实不会改变这一点,也不会使此字典神奇地变为可变。

这就是为什么@Wain正确建议使用mutableCopy使NSDictionary成为NSMutableDictionary的原因,以便您可以在其上调用setValue:forKey:setObject:forKey:。另一种方法是使用[NSMutableDictionary dictionaryWithDictionary:@{ … }];来创建可变字典。


事实上,如果-Wincompatible-pointer-types警告是开启的,默认情况下就是这种情况,那么你应该有warning: incompatible pointer types initializing 'NSMutableDictionary *' with an expression of type 'NSDictionary *' 之类的警​​告,这些警告应该会引导您进入问题的原因及其解决方案。 (总是阅读警告,这不是因为它们只是警告而且它们不会使编译失败,因为它们并不重要!)

答案 2 :(得分:1)

只需添加“mutableCopy”即可创建NSMutableDictionary类型的字典

NSMutableDictionary *dict = [@{ @"myfield1" : @{  @"subfield1" : @"mysubfield1" ,
                                                     @"subfield2" : @"mysubfield2" },
                                   @"myfield2": @"myfield2",
                                   @"myfield3": @"myfield3"} mutableCopy];

NSMutableDictionary *newdict =  [@{  @"subfield1" : @"mynewsubfield1" ,
                                        @"subfield2" : @"mynewsubfield2" } mutableCopy];


dict[@"myfield1"]=newdict;