运行这段代码:
NSData *jsonData = [@"{\"foo\":\"bar\"}" dataUsingEncoding:NSUTF8StringEncoding];
id result = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
if ([result isKindOfClass:[NSMutableDictionary class]])
{
NSMutableDictionary *dict = (NSMutableDictionary *)result;
[dict setObject:@"foo" forKey:@"baz"];
}
并且您从 setObject
调用中得到了这个异常:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
当使用顶级字典对象解析 JSON 时,NSJSONSerialization
返回一个不可变的字典对象,表明它是一个 NSMutableDictionary
但当您尝试改变它时抛出异常.
我知道我可以通过 NSJSONReadingMutableContainers
选项来获取可变容器。但幕后发生了什么?为什么一个类说它是一个可变的子类,但随后却表现得好像它是不可变的?
编辑以澄清问题:我知道有几种方法可以使此代码正常工作。我可以对结果调用 mutableCopy
或使用 NSJSONReadingMutableContainers
选项来获得可变结果。这里的重点是一个对象说它的类型是 NSMutableDictionary
或其子类,然后当我尝试改变它时它会导致崩溃。为什么会存在这种行为?它应该被认为是一个错误吗?或者这是 Objective-C 运行时的一些预期怪癖?
最佳答案
因为您试图在 result
(您的 NSCFDictionary -- 不可变)而不是 dict
(您的转换 NSMutableDictionary)上为键设置对象。
相反,尝试:
NSData *jsonData = [@"{\"foo\":\"bar\"}" dataUsingEncoding:NSUTF8StringEncoding];
id result = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
if ([result isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dict = [result mutableCopy];
[dict setObject:@"foo" forKey:@"baz"];
}
当您尝试确定结果是否适合 NSMutableDictionary 类时,结果传递为 true 的原因是因为 NSCFDictionary 是一个匹配 NSDictionary 和 NSMutableDictionary 的类簇。 (参见 What is an NSCFDictionary?)。
本质上(在那个 if 语句中),您实际上根本没有检查 NSCFDictionary 是否可变——您只是检查它是否是 NSMutableDictionary 的子类(或成员类)。
关于ios - 对象是 NSMutableDictionary 的子类,但在 mutate 方法 (NSJSONSerialization) 上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24542286/