用于创建 NSDictionary 的 Objective-C foreach 不起作用

Posted

技术标签:

【中文标题】用于创建 NSDictionary 的 Objective-C foreach 不起作用【英文标题】:Objective-C foreach for creating a NSDictionary not working 【发布时间】:2014-03-17 13:38:06 【问题描述】:

我正在尝试使用以下代码对 NSDictionary 进行排序:

NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:&err];
for (NSDictionary* lesson in jsonDict[@"data"][@"lessons"]) 
    data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];

如果我记录lesson[@"day"] 等的值,这些值似乎是正确的。不知何故,如果我在循环之后记录data[@"1"][@"1"],它只是空的。所以问题似乎在于将值设置到 NSDictionary 数据中。

原始 JSON 字符串包含一个包含所有课程的列表。为了正确访问它们,我想要一个新的 NSDictionary 格式:data[day][index][field]

JSON 代码如下所示:

"status":"success","data":"lessons":["id":1,"index":"1","day":"1","title":"Mathe","teacher":"Mr. xyz","room":"103","ind":"1","id":2,"index":"1","day":"2","title":"Physik","teacher":"Mr xyz","room":"PH4","ind":"1",...

【问题讨论】:

你能发一个 JSON 的例子吗? “重新排序字典”?说什么? NSMutableDictionary Class Reference @jackslash 我添加了 JSON 示例的一部分,尽管这不是问题。我可以成功访问数据,问题只是将它放入一个新的 NSDictionary(在 for 循环中) @Dion 问题是你不能像那样修改NSDictionary,你需要一个可变容器,在你的情况下是NSMutableDictionary 【参考方案1】:

问题是(我假设)

data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];

不会自动创建中间字典

data[lesson[@"day"]]
data[lesson[@"day"]][lesson[@"index"]]

您必须先检查它们是否存在,如果它们还不存在,则分配一个可变字典 存在。 (没有 Autovivification 与 Perl 哈希一样!)类似于:

if (data[lesson[@"day"]] == nil) 
    data[lesson[@"day"]] = [NSMutableDictionary dictionary];

if (data[lesson[@"day"]][lesson[@"index"]] == nil) 
    data[lesson[@"day"]][lesson[@"index"]] = [NSMutableDictionary dictionary];

data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];

完整的工作代码:

NSString *str = @"\"status\":\"success\",\"data\":\"lessons\":[\"id\":1,\"index\":\"1\",\"day\":\"1\",\"title\":\"Mathe\",\"teacher\":\"Mr. xyz\",\"room\":\"103\",\"ind\":\"1\",\"id\":2,\"index\":\"1\",\"day\":\"2\",\"title\":\"Physik\",\"teacher\":\"Mr xyz\",\"room\":\"PH4\",\"ind\":\"1\"]";
NSError *err;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:&err];
NSMutableDictionary *data = [NSMutableDictionary dictionary];

for (NSDictionary* lesson in jsonDict[@"data"][@"lessons"]) 
    if (data[lesson[@"day"]] == nil) 
        data[lesson[@"day"]] = [NSMutableDictionary dictionary];
    
    if (data[lesson[@"day"]][lesson[@"index"]] == nil) 
        data[lesson[@"day"]][lesson[@"index"]] = [NSMutableDictionary dictionary];
    
    data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];

NSLog(@"%@", data);

输出:

1 = 1 = 标题=数学; ; ; 2 = 1 = 标题=物理; ; ;

【讨论】:

这看起来完全正确,实际上正是我正在寻找的东西,但不知何故它也不起作用:/如果我完全采用您的代码,则会出现错误“未找到编写字典元素的预期方法在“NSDictionary *”类型的对象上,如果我将其更改为 setValue:... forKey:... 输出仍然为空,并且内容不会像以前那样写入新的 NSDictionary :( @Dion:第一条错误消息意味着你有一个(不可变的)NSDictionary,而不是一个 NSMutableDictionary。并且你应该使用setObject:forKey来设置字典值,除非你有特定的理由使用Key-Value编码方式setValue:forKey:。 - 我已经用您的输入数据测试了代码,它似乎可以工作。查看更新的答案。 它没有立即起作用的原因是我的错。您的回答完全正确并且有效:) 非常感谢!【参考方案2】:

NSJSONSerialization 创建字典和数组,其中填充了其他字典、数组和 NSString、NSNumber 或 NSNull 类型的值。

您应该重新考虑编写极其复​​杂的代码行的策略,但要逐个提取内容,以减少混乱,并使调试成为可能。喜欢

NSDictionary* data = jsonDict [@"data"];
NSArray* lessons = data [@"lessons"];

for (NSDictionary* lesson in lessons)

    NSString* lessonDay = lesson [@"day"];
    ...

等等(如果您不一次又一次地查找相同的东西,它也会使您的代码运行得更快)。

现在到您的错误所在的位置:dict [@"key"] = data;调用 setObject:forKey: 。但是, dict [@"key1"] [@"key2"] 在字典上调用 objectForKey: @"key1" ,这会给你一个 nil 值,然后 setObjectForKey: 将被一个 nil 接收器调用。

【讨论】:

嗯,好的,谢谢您的回答,但究竟如何才能解决这个问题?

以上是关于用于创建 NSDictionary 的 Objective-C foreach 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

我的 NSDictionary 在我的 IBAction 中变为零

用于回调的 iOS NSError/NSDictionary

用于 JSON 解析的 NSDictionary 或自定义 NSObject

writeToFile 不适用于 NSDictionary [重复]

从两个 NSArrays 中包含的数据准备一个 NSDictionary 用于 UITableView

用法总结:NSArray,NSSet,NSDictionary-备用