iOS开发中NSMutableDictionary的setValue:forKey:偶发崩溃修复咨询
Objective-C 代码偶发崩溃修复方案
问题描述
以下代码存在偶发崩溃情况:
-(void)addCallbackOfFileType:(SendFileType)fileType callback:(sendProcess)callback target:(id)target{ [_hashTable addObject:target]; NSString * targetKeyStr = NSStringFromClass([target class]); if (callback && targetKeyStr) { NSString * fid = [NSString stringWithFormat:@"%d",(int)fileType+KBigFileAdded]; NSMutableDictionary * targetMdic = [[NSMutableDictionary alloc]init]; if ([_callbacks valueForKey:targetKeyStr]) { targetMdic = [_callbacks valueForKey:targetKeyStr]; } [targetMdic setValue:callback forKey:fid]; [_callbacks setValue:targetMdic forKey:targetKeyStr]; } }
崩溃发生在这一行:
[targetMdic setValue:callback forKey:fid];
崩溃截图:
崩溃原因
从截图报错-[__NSDictionaryI setValue:forKey:]: unrecognized selector sent to instance可以明确:
_callbacks中存储的字典可能是不可变字典(__NSDictionaryI),但代码直接将其赋值给NSMutableDictionary类型变量targetMdic- 调用可变字典的
setValue:forKey:方法时,实际对象是不可变字典,因此触发未识别选择器崩溃 - 另外,使用KVC方法
valueForKey:取值不如字典标准的objectForKey:安全,容易出现非预期类型问题
修复代码
-(void)addCallbackOfFileType:(SendFileType)fileType callback:(sendProcess)callback target:(id)target{ [_hashTable addObject:target]; NSString * targetKeyStr = NSStringFromClass([target class]); if (callback && targetKeyStr) { NSString * fid = [NSString stringWithFormat:@"%d",(int)fileType+KBigFileAdded]; // 用字典标准方法取值,替代KVC的valueForKey: NSDictionary *existingDict = [_callbacks objectForKey:targetKeyStr]; NSMutableDictionary *targetMdic = nil; if (existingDict) { // 校验原有字典类型,不可变则转成可变字典 if ([existingDict isKindOfClass:[NSMutableDictionary class]]) { targetMdic = (NSMutableDictionary *)existingDict; } else { targetMdic = [NSMutableDictionary dictionaryWithDictionary:existingDict]; } } else { // 无已有字典则新建可变字典 targetMdic = [[NSMutableDictionary alloc] init]; } [targetMdic setValue:callback forKey:fid]; // 用字典标准方法存值,替代KVC的setValue:forKey: [_callbacks setObject:targetMdic forKey:targetKeyStr]; } }
额外优化提示
- 字典操作优先使用
objectForKey:/setObject:forKey:,而非KVC方法,避免隐式类型转换带来的问题 - 对取出的对象必须做类型校验,确保是预期类型后再直接操作,不可变类型需转成可变类型后再修改
内容的提问来源于stack exchange,提问作者user7522836
相关产品推荐
相关产品推荐

