I have a NSMutableArray instance, named arr1, stored in a NSMutableDictionary, using [writeToFile:] to serialize the dictionary.
After then I deserialize the dictionary using [contentsOfFile:] method. Then fetch the array, named arr2, from this new dictionary.
Then, when [arr2 addObject:aString] is called, intresting things happen:
If arr2 has at least 1 elements, the above call succeed and the aString object is added to arr2 successfully.
If arr2 is empty, an NSInternalInconsistencyException raised, says: mutating method sent to immutable object.
What is the difference? In the above two cases, [arr2 class] returns a "__NSCFArray" class, and [[arr2 class] superClass] returns NSMutableArray !!!
Since arr2 is kind of NSMutableArray, what does this " mutating method sent to immutable object" mean ?
The following are the sample code and its output:
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSLog(@"%@", path);
path = [path stringByAppendingPathComponent:@"arrayTest.plist"];
NSMutableArray *marr1 = [NSMutableArray array];
[marr1 addObject:@"arr1_ele1"];
NSArray *marr11 = [NSArray arrayWithObjects:@"arr11_ele1", nil];
NSMutableArray *marr2 = [NSMutableArray array];
NSArray *marr22 = [NSArray array];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:marr1 forKey:@"arr1"];
[dict setObject:marr2 forKey:@"arr2"];
[dict setObject:marr11 forKey:@"arr11"];
[dict writeToFile:path atomically:YES];
NSLog(@"marr1 class:%@, marr11 class:%@", [marr1 class], [marr11 class]);
NSLog(@"marr2 class:%@, marr22 class:%@", [marr2 class], [marr22 class]);
NSLog(@"************ UnSerialized form file ******************");
NSDictionary *dict2 = [NSDictionary dictionaryWithContentsOfFile:path];
marr1 = [dict2 objectForKey:@"arr1"];
marr11 = [dict2 objectForKey:@"arr11"];
marr2 = [dict2 objectForKey:@"arr2"];
marr22 = [[marr2 mutableCopy] autorelease];
NSLog(@"marr1 class: %@, kind of NSMutableArray:%zd, member of NSMutableArray:%zd, super:%@", [marr1 class], [marr1 isKindOfClass:[NSMutableArray class]], [marr1 isMemberOfClass:[NSMutableArray class]], [[marr1 class] superclass]);
NSLog(@"marr2 class: %@, kind of NSMutableArray:%zd, member of NSMutableArray:%zd, super:%@", [marr2 class], [marr2 isKindOfClass:[NSMutableArray class]], [marr2 isMemberOfClass:[NSMutableArray class]], [[marr2 class] superclass]);
try {
NSLog(@"trying to add marr1...");
[marr1 addObject:@"ele2"];
} catch (NSException *e) {
NSLog(@"%@", e);
}
NSLog(@"marr1 class: %@, marr1 content: %@", [marr1 class], marr1);
try {
NSLog(@"trying to add marr11...");
[marr11 addObject:@"ele2"];
} catch (NSException *e) {
NSLog(@"%@", e);
}
NSLog(@"marr11 class: %@, marr11 content: %@", [marr11 class], marr11);
try {
NSLog(@"trying to add marr2...");
[marr2 addObject:@"ele2"];
} catch (NSException *e) {
NSLog(@"%@", e);
}
NSLog(@"marr2 class: %@, marr2 content: %@", [marr2 class], marr2);
try {
NSLog(@"trying to add marr22...");
[marr22 addObject:@"ele22"];
} catch (NSException *e) {
NSLog(@"%@", e);
}
NSLog(@"marr22 class: %@, marr22 content: %@", [marr22 class], marr22);Output results:
marr1 class:__NSArrayM, marr11 class:__NSArrayI
marr2 class:__NSArrayM, marr22 class:__NSArray0
************ UnSerialized form file ******************
marr1 class: __NSCFArray, kind of NSMutableArray:1, member of NSMutableArray:0, super:NSMutableArray
marr2 class: __NSCFArray, kind of NSMutableArray:1, member of NSMutableArray:0, super:NSMutableArray
trying to add marr1...
marr1 class: __NSCFArray, marr1 content: (
"arr1_ele1",
ele2
)
trying to add marr11...
marr11 class: __NSCFArray, marr11 content: (
"arr11_ele1",
ele2
)
trying to add marr2...
-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object
marr2 class: __NSCFArray, marr2 content: (
)
trying to add marr22...
marr22 class: __NSCFArray, marr22 content: (
ele22
)