【发布时间】:2014-07-02 22:47:43
【问题描述】:
运行此代码:
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 调用中得到这个异常:
* 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object”
使用顶级字典对象解析 JSON 时,NSJSONSerialization 返回一个不可变的字典对象,表示它是一个 NSMutableDictionary,但在您尝试对其进行变异时抛出异常。
我知道我可以通过NSJSONReadingMutableContainers 选项来获取可变容器。但是引擎盖下发生了什么?为什么一个类说它是一个可变的子类,然后表现得好像它是不可变的?
编辑以澄清问题:我知道有几种方法可以使此代码正常工作。我可以在结果上调用mutableCopy 或使用NSJSONReadingMutableContainers 选项来获得可变结果。这里的重点是一个对象说它的类型是NSMutableDictionary 或其子类,然后当我尝试对其进行变异时它会导致崩溃。为什么会存在这种行为?它应该被认为是一个错误吗?或者这是 Objective-C 运行时的一些预期怪癖?
【问题讨论】:
-
我没有继承
NSDictionary或NSMutableDictionary。 -
您在问题标题中混淆了“子类”和“实例”。
-
查看 Apple 的 Concepts in Objective-C Programming 指南中关于 Object Mutability 的部分。其中一个子标题为:使用返回类型,而不是自省。下面是一段摘录:“[Y] 你不应该根据类成员资格对对象是否可变做出假设。您的决定应该完全由出售对象的方法的签名说明其可变性的内容来指导。”
-
类集群可能看起来很奇怪,但它们允许 Apple 的工程师对频繁使用的类进行一些非常有价值的性能优化。
-
NSJSONSerialization 的返回类型,在没有 mutable 选项的情况下,总是不可变的。
标签: ios objective-c nsdictionary nsmutabledictionary nsjsonserialization