【问题标题】:setObject: forKey: crashes when used on multi-dim NSMuteableDictionarysetObject: forKey: 在多维度 NSMuteableDictionary 上使用时崩溃
【发布时间】:2016-05-10 22:34:52
【问题描述】:

我有一个 NSMutableDictionary,里面有一系列的部分元素。我需要更改子部分中的其中一个元素。

所以我从返回的对象中创建了一个 NSMutableDictionary,我想修改它,然后在主 NSMutableDictionary 中替换它。

        int intTagToFind = 1;
        NSLog(@"Finding tag %u",intTagToFind);
        for (int i=0; i < returnDict.count; i++){
            NSString *keyString = [NSString stringWithFormat: @"section%03d",i];
            NSMutableDictionary *sectionData = [returnDict objectForKey:keyString];
            for (int j=0; j<sectionData.count; j++) {
                int myTag = [[sectionData objectForKey:@"tag"] intValue];
                if (myTag == intTagToFind){
                    NSLog(@"Found Tag: %u %u",myTag,intTagToFind);
                    NSLog(@"Key to finding is %@",keyString);
                    NSLog(@"Header is:%@",[sectionData objectForKey:@"section header"]);
                    NSLog(@"Class: %@",[sectionData class]);
                    NSLog(@"Class: %@",[returnDict class]);


[sectionData setObject:@"new header here" forKey:@"section header"];
                    NSLog(@"New Header is:%@",[sectionData objectForKey:@"section header"]);

                }
            }
        }

它给出:[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0x7f9414110080

当我使用以下命令创建 sectionData 时:NSMutableDictionary *sectionData = [returnDict objectForKey:keyString];

返回类名为 __NSDictionaryI 而 returnDict 是类名:__NSDictionaryM

为什么它给了我错误的类型?你不能从 objectForKey 得到一个可变字典吗?

以下是将数组转换为字典的代码:

NSMutableDictionary *returnDict = [[NSMutableDictionary alloc] init];
for(int i=0; i < [returnData count] - 1; i++)
{
    [returnDict setObject:[returnData objectAtIndex:i+1] forKey:[NSString stringWithFormat: @"section%03d", i]];
}

下面是数组的样例:

NSArray *returnData = @[ @{ @"section header": @"Business News",
                                        @"sub header": @"Investing news",
                                        @"sub header scroll": @"0",
                                        @"sub button": @"Delete",
                                        @"tag":@"0",
                                        @"articles": @[ @{ @"title": @"One" },
                                                        @{ @"title": @"Longer" },
                                                        @{ @"title": @"Even Longer" },
                                                        @{ @"title": @"Still Much Longer" },
                                                        @{ @"title": @"Really Long Title Here Now." }
                                                        ]
                                        },

我使用 'tag' 作为唯一 ID。

我创建数组,将数组加载到字典中,然后想要更改标题、按钮等内部元素...使用标签作为唯一 ID。

【问题讨论】:

  • 您能否显示将 sectionData Dictionaries 插入 returnDict 的代码?
  • 嵌套字典是不可变的。您需要确保它们是可变的。我建议改为使用一个 NSObjects 数组。
  • @Andy,嵌套字典可以是可变和不可变的任何组合。这取决于它们是如何创建的。例如,如果您使用 NSJSONSerialization 从 JSON 数据中读取嵌套容器对象并指定选项 NSJSONReadingMutableContainers +NSJSONReadingMutableLeaves,则生成的对象图中的容器对象和“叶”字符串对象都是可变的。
  • @Andy,我刚刚注意到 OPs 问题的第二部分,他在其中展示了创建字典的代码。同意以这种方式创建字典确实会创建不可变字典,但您评论的措辞听起来像是嵌套字典始终是不可变的,这是不正确的。
  • @DuncanC 上面的异常表明 nsdictionary 是不可变的

标签: ios objective-c nsmutabledictionary


【解决方案1】:

这段代码:

NSMutableDictionary *sectionData = [returnDict objectForKey:keyString];

不创建可变字典。它获取键 keyString 处的 returnDict 中的任何内容,并将其转换为 NSMutableDictionary 类型。底层对象不会改变。

此时您实际上已从 returnDict 共享对象的所有权。如果对象在returnDict 中是不可变的,则它将保持不可变。

你可能想这样做:

NSDictionary *immutableSectionData = [returnDict objectForKey:keyString];
NSMutableDictionary *sectionData = [immutableSectionData mutableCopy];

(上面的代码被分成两行只是为了便于在狭窄的 SO 文本视图中阅读。)

编辑:

事实上,如果您帖子中的第二个代码块是您创建数据结构的方式,那么整个事情是不可变的。您将无法更改任何内容。

【讨论】:

  • 好的 Duncan C 是正确的,上面的第二个代码块是问题的根源。我通过将它保存到一个文件并从该文件加载它做了一个廉价的工作。我想知道如何以更直接的方式使用 multi-Dim 加载 NSMuteableDictionary。也许这是一个新问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 1970-01-01
相关资源
最近更新 更多