Reputation: 3811
While validating for null values ,the crashes with
-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object
When I am using all mutable type.(crashing only in iOS 9,other versions of my app in Appstore are working fine)
Can anyone suggest me how to handle this at null condition to setValue for key.
NSMutableArray *tempelementsArray=[[NSMutableArray alloc]init];
if(![[catDic objectForKey:@"menuElementList"] isEqual:@""]){
tempelementsArray = [catDic objectForKey:@"menuElementList"];
if(tempelementsArray != nil && [tempelementsArray count]>0)
{
for (NSInteger j=0; j<tempelementsArray.count; j++) {
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
[elementDic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNull class]])
{
[elementDic setValue:@"" forKey:key];//App crashes here when one of the value is NULL
}
} ];
}
with below crash:
*** Terminating app due to uncaught exception NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** First throw call stack:
(
0 CoreFoundation 0x00df3a94 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0051be02 objc_exception_throw + 50
2 CoreFoundation 0x00df39bd +[NSException raise:format:] + 141
3 CoreFoundation 0x00d0ed68 -[__NSCFDictionary setObject:forKey:] + 104
4 Foundation 0x001051ba -[NSMutableDictionary(NSKeyValueCoding) setValue:forKey:] + 68
5 coreDataMenuSample 0x000481d9 __33-[ViewController SaveToCoredata:]_block_invoke188 + 217
6 CoreFoundation 0x00df2849 ____NSDictionaryEnumerate_block_invoke417 + 41
7 CoreFoundation 0x00cd5452 CFBasicHashApply + 130
8 CoreFoundation 0x00d12481 __NSDictionaryEnumerate + 273
9 CoreFoundation 0x00d122ed -[NSDictionary enumerateKeysAndObjectsWithOptions:usingBlock:] + 45
10 CoreFoundation 0x00d12235 -[NSDictionary enumerateKeysAndObjectsUsingBlock:] + 53
11 coreDataMenuSample 0x00043e71 -[ViewController SaveToCoredata:] + 6481
12 coreDataMenuSample 0x0004239d -[ViewController viewDidLoad] + 893
13 UIKit 0x0133fd74 -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 44
14 UIKit 0x013448c2 -[UIViewController loadViewIfRequired] + 1556
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I have even checked this similar issue Strange “mutating method sent to immutable object” error when adding an object to a mutable array
Saving CLLocation error: Mutating method sent to immutable object
Upvotes: 0
Views: 2236
Reputation: 5563
There are several things wrong with your code :
First it's not because you initialise a variable with a mutable object that subsequent initialisations will be converted to mutable objects. So when you do :
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
elementDic
contains whatever was in the array at index j
, so in this case probably an immutable object. You have to make mutable copies of your objects if you want them mutable.
Second, you can't mutate a dictionary while you enumerate it (which is what you are trying to do here). You have to make a mutable copy and mutate the copy while you enumerate the original.
Third, if you expect [catDic objectForKey:@"menuElementList"]
to be an array, why do you test if it's equal to an empty string ?!
Here is a fixed version of your code (with modern obj-C syntax which is much easier to read by the way)
NSDictionary *catDic = ...
NSArray *tempElementsArray = catDic[@"menuElementList"];
NSMutableArray *mutableTempElementsArray = [NSMutableArray arrayWithCapacity:tempElementsArray.count];
if (![tempElementsArray isEqual:@""] && tempElementsArray != nil && tempElementsArray.count > 0)
{
for (NSUInteger j = 0; j < tempElementsArray.count; j++)
{
NSDictionary *elementsDic = tempElementsArray[j];
NSMutableDictionary *mutableElementsDic = [NSMutableDictionary dictionaryWithCapacity:elementsDic.count];
[elementsDic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if (obj == [NSNull null]) {
obj = @"";
}
mutableElementsDic[key] = obj;
}];
[mutableTempElementsArray addObject:mutableElementsDic];
}
}
NSMutableDictionary *mutableCatDic = [NSMutableDictionary dictionaryWithDictionary:catDic];
mutableCatDic[@"menuElementList"] = mutableTempElementsArray;
Upvotes: 1
Reputation: 2859
Look at your code, I think the problem is this line
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
tempelementsArray
contains an instance of NSDictionary
instead of NSMutableDictionary
. Change to this code will help:
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]initWithDictionary:tempelementsArray[j]];
Upvotes: 5