Run this code:
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"];
}
And you get this exception from the setObject
call:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
When parsing JSON with a top-level dictionary object, NSJSONSerialization
returns an immutable dictionary object that says it's a an NSMutableDictionary
but throws an exception when you try to mutate it.
I know I can pass the NSJSONReadingMutableContainers
option to get mutable containers. But what is going on here under the hood? Why does a class say it's a mutable subclass but then behave as if it's immutable?
Edit to clarify question: I know there are several ways to make this code work. I could call mutableCopy
on the result or use the NSJSONReadingMutableContainers
option to get mutable results. The point here is that an object says its type is NSMutableDictionary
or a subclass thereof, and then it causes a crash when I try to mutate it. Why does this behavior exist? Should it be considered a bug? Or is this some expected quirk of the Objective-C runtime?