Ios '-setValue:forKey:';更新NSMutableDictionary的字段时出现异常
我有两个名为“dict”和newdict的NSMutableDictionary对象。然后尝试将newdict分配给“myfield1”字段。然而,我面临一个错误Ios '-setValue:forKey:';更新NSMutableDictionary的字段时出现异常,ios,iphone,objective-c,Ios,Iphone,Objective C,我有两个名为“dict”和newdict的NSMutableDictionary对象。然后尝试将newdict分配给“myfield1”字段。然而,我面临一个错误 NSMutableDictionary *dict = @{ @"myfield1" : @{ @"subfield1" : @"mysubfield1" , @"subfield2" : @"mysubfield2" },
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.'
***由于未捕获的异常“NSUnknownKeyException”而终止应用程序,
原因:'[setValue:forUndefinedKey:]:
此类不符合密钥loc的密钥值编码要求。”
如何解决此问题?不要使用
setValue:forKey:
,因为这是一种KVC方法,而不是字典方法。使用setObject:forKey:
。从技术上讲,KVC方法是可行的,但是您通常只应该在有特定需要时使用它
你真正的问题是你的字典实例是不可变的。使用
mutableCopy
从文字定义创建可变版本。文字定义总是不可变的。正如@Wain所解释的,您的字典实例是不可变的
可能让您感到困惑的是,您将变量声明为NSMutableDictionary
,因此您认为它们是可变的。但是这个@{…}
文本语法相当于[NSDictionary Dictionary WithObjects:forKeys:count:
,因此创建了一个(不可变的)NSDictionary
实例
您将此值影响到类型为NSMutableDictionary
的变量这一事实不会改变这一点,也不会使此dictionary神奇地可变。
这就是为什么@Wain正确地建议使用mutableCopy
使这个NSDictionary
成为一个NSMutableDictionary
,这样你就可以调用setValue:forKey:
或setObject:forKey:
。另一种方法是使用[NSMutableDictionary:@{…}];
创建可变字典
事实上,如果
-Wincompatible pointer types
警告处于启用状态(默认情况下应该是这样),您应该会收到类似警告的警告:不兼容的指针类型使用类型为“NSDictionary*”的表达式初始化“NSMutableDictionary*”
,这应该会引导您找到问题的原因,并它的解决方案。(始终阅读警告,这并不是因为它们只是警告,它们不会导致编译失败,因为它们并不重要!)只需添加“mutableCopy”即可使您的字典成为NSMutableDictionary类型
NSMutableDictionary *dict = [@{ @"myfield1" : @{ @"subfield1" : @"mysubfield1" ,
@"subfield2" : @"mysubfield2" },
@"myfield2": @"myfield2",
@"myfield3": @"myfield3"} mutableCopy];
NSMutableDictionary *newdict = [@{ @"subfield1" : @"mynewsubfield1" ,
@"subfield2" : @"mynewsubfield2" } mutableCopy];
dict[@"myfield1"]=newdict;
您需要使用setObject:forKeyYep,仅仅声明一个字典是可变的(通过指针)并不能使它变为可变的表示法是不可变的。不同意你的第一点。
setValue:forKey
有一个特定的、有文档记录的可变字典实现,如果你传入一个nil对象,它将删除它,而setObject会崩溃。@jrturton很好,我做了一些修改,试图更清楚,谢谢。