在验证空值时,使用
崩溃- [__ NSCFDictionary setObject:forKey:]:发送到不可变对象的mutating方法
当我使用所有可变类型时。(仅在iOS 9中崩溃,Appstore中其他版本的应用程序正常运行)
任何人都可以建议我如何在null条件下处理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
}
} ];
}
以下崩溃:
*** 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
我甚至检查过类似的问题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
答案 0 :(得分:5)
看看你的代码,我认为问题就在这一行
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
tempelementsArray
包含NSDictionary
而不是NSMutableDictionary
的实例。更改此代码将有所帮助:
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]initWithDictionary:tempelementsArray[j]];
答案 1 :(得分:1)
您的代码有几个问题:
首先,它不是因为您使用可变对象初始化变量,后续初始化将转换为可变对象。所以当你这样做时:
NSMutableDictionary *elementDic = [[NSMutableDictionary alloc]init];
elementDic = [tempelementsArray objectAtIndex:j];
elementDic
包含索引j
中数组中的内容,因此在这种情况下可能是一个不可变对象。如果你想要它们是可变的,你必须制作对象的可变副本。
其次,在枚举字典时不能改变字典(这是你在这里尝试做的)。您必须制作一个可变副本并在枚举原始文件时改变副本。
第三,如果你希望[catDic objectForKey:@"menuElementList"]
成为一个数组,为什么要测试它是否等于一个空字符串?!
以下是您的代码的固定版本(使用现代obj-C语法,顺便说一下,它更容易阅读)
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;