You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 10:00:27