Xcode 重复的 NSDictionary
Xcode Duplicate NSDictionary
我有两部词典有问题。在我的头文件中,我声明了一个字典:
@property (strong, nonatomic) NSMutableDictionary *templateDictionary
templateDictionary 保存字符串和字典,例如'blankCopy',它又保存其他字符串和字典。我也在我的实现文件中声明了一个字典:
@property (strong, nonatomic) NSMutableDictionary *exampleDictionary
在我的实现中,我试图将 exampleDictionary 的一部分设置为 templateDictionary 的一部分,如下所示:
[self.exampleDictionary setObject:[templateDictionary objectForKey:@"blankCopy"] forKey:@"template"];
在我更改 exampleDictionary 'template' 中的任何内容之前,此方法一直有效。现在,当我回到 templateDictionary 时,它也发生了变化。我想这是因为它在向后指。我尝试了以下但都没有任何效果:
[self.exampleDictionary setObject:[[templateDictionary objectForKey:@"blankCopy"] copy] forKey:@"template"];
[self.exampleDictionary setObject:[[templateDictionary objectForKey:@"blankCopy"] mutableCopy] forKey:@"template"];
[self.exampleDictionary setObject:[NSMutableDictionary dictionaryWithDictionary:[templateDictionary objectForKey:@"blankCopy"]] forKey:@"template"];
关于问题所在以及如何修复它,或者如何按值复制字典对象有什么想法吗?
这里的问题是字典只保留对包含对象的引用。当您复制字典时,您只是在复制引用,而不是对象。因此,如果您在一个字典中修改某些内容,您会在另一个字典中看到它被修改。
解决办法是对字典的内容进行深拷贝,即对每个存入字典的对象,如果也是字典,则深拷贝存入新的字典。
您可以查看示例 at this answer,其中有实现。
首先,题外话:你不需要这样做:
[self.exampleDictionary setObject:[templateDictionary objectForKey:@"blankCopy"] forKey:@"template"];
这更容易阅读:
self.exampleDictionary[@"template"] = templateDictionary[@"blankCopy"];
您会看到旧代码写得像第一行,但对于新代码,第二行要好得多。该语法在 Xcode 中已经工作了至少两年。
你遇到的真正问题是 [NSMutableDictionary mutableCopy]
只是一个浅拷贝——它是一个新字典,但字典中的值是引用的,而不是复制的。你需要一个深拷贝。查看 http://samwize.com/2014/05/12/deep-copying-of-nsarray-slash-nsdictionary-slash-any-object/ for an approach using NSKeyedUnarchiver
or https://gist.github.com/yfujiki/1664847 以获得直接(但更详细)的方法。
我有两部词典有问题。在我的头文件中,我声明了一个字典:
@property (strong, nonatomic) NSMutableDictionary *templateDictionary
templateDictionary 保存字符串和字典,例如'blankCopy',它又保存其他字符串和字典。我也在我的实现文件中声明了一个字典:
@property (strong, nonatomic) NSMutableDictionary *exampleDictionary
在我的实现中,我试图将 exampleDictionary 的一部分设置为 templateDictionary 的一部分,如下所示:
[self.exampleDictionary setObject:[templateDictionary objectForKey:@"blankCopy"] forKey:@"template"];
在我更改 exampleDictionary 'template' 中的任何内容之前,此方法一直有效。现在,当我回到 templateDictionary 时,它也发生了变化。我想这是因为它在向后指。我尝试了以下但都没有任何效果:
[self.exampleDictionary setObject:[[templateDictionary objectForKey:@"blankCopy"] copy] forKey:@"template"];
[self.exampleDictionary setObject:[[templateDictionary objectForKey:@"blankCopy"] mutableCopy] forKey:@"template"];
[self.exampleDictionary setObject:[NSMutableDictionary dictionaryWithDictionary:[templateDictionary objectForKey:@"blankCopy"]] forKey:@"template"];
关于问题所在以及如何修复它,或者如何按值复制字典对象有什么想法吗?
这里的问题是字典只保留对包含对象的引用。当您复制字典时,您只是在复制引用,而不是对象。因此,如果您在一个字典中修改某些内容,您会在另一个字典中看到它被修改。
解决办法是对字典的内容进行深拷贝,即对每个存入字典的对象,如果也是字典,则深拷贝存入新的字典。
您可以查看示例 at this answer,其中有实现。
首先,题外话:你不需要这样做:
[self.exampleDictionary setObject:[templateDictionary objectForKey:@"blankCopy"] forKey:@"template"];
这更容易阅读:
self.exampleDictionary[@"template"] = templateDictionary[@"blankCopy"];
您会看到旧代码写得像第一行,但对于新代码,第二行要好得多。该语法在 Xcode 中已经工作了至少两年。
你遇到的真正问题是 [NSMutableDictionary mutableCopy]
只是一个浅拷贝——它是一个新字典,但字典中的值是引用的,而不是复制的。你需要一个深拷贝。查看 http://samwize.com/2014/05/12/deep-copying-of-nsarray-slash-nsdictionary-slash-any-object/ for an approach using NSKeyedUnarchiver
or https://gist.github.com/yfujiki/1664847 以获得直接(但更详细)的方法。