1

我有一个奇怪的问题,我已经研究/玩了几个小时了。

我正在开发一个简单的笔记应用程序,将笔记存储在NSMutableDictionary以键为标题和值作为笔记的方式中。我有一个委托函数,NSTextView每次更改时都会保存它的内容。

-(void)textDidChange:(NSNotification *)notification {
    NSString *currentNote = [_mainTextField string];
    [Data setNote:currentNote forKey:currentKey];
}

然后将其添加到字典中。

+(void)setNote:(NSString *)note forKey:(NSString *)key {
    [allNotes setObject:note forKey:key];
}

whilecurrentKey是一个在其他地方更新的全局变量(我已经彻底测试并且工作正常)。

这就是奇怪的地方:setNote:forKey:只要键都是唯一的(它们是),您会期望字典为每次调用更新一个键。但相反,它每次都会更新所有先前更新的密钥。 因此,如果您有这样的字典。

"John" = "apples";
"David" = "apples";

你将“John”更新为“bananas”

"John" = "bananas";
"David" = "apples";

然后你将“David”更新为“oranges”,你会得到这个:

"John" = "oranges";
"David" = "oranges";

我已经断点和 NSLog'd 了,我发现“John”在setNote:forKey:方法开始时变成了“oranges”,甚至在调用[allNotes setObject:note forKey:key]行之前。 现在,这是我整个程序中唯一更改allNotesDictionary 的地方,但不知何故,在调用函数之前,原始行就被重新更改了。第一次进行更改(“香蕉”轮)时,无论字典的大小或正在更改的条目如何,一切都可以正常工作,第二次(“橙子”轮)一切正常,除了也更改先前更改的行。

我不知道如何更准确地了解我的代码中的原因,因为在按下某个键的那一刻,textDidChange:就会调用它,并且到那时第一个条目已经被更改。值得注意的是,当我停止应用程序并重新运行时,它会恢复正常更改第一个应用程序,然后重新开始整个过程​​。

另一个奇怪的部分是,关键变量工作正常。我已经在调试器中检查过:全局变量currentKey和从它派生的局部变量key都是“David”,但是这些更改会同时影响“David”和“John”,以及在“John”之前更改的任何其他变量. 它怎么可能知道之前编辑了哪些行,而只有当前的 Key 值可以使用?

诚然,我是一个 Cocoa 初学者,但我完全被难住了。任何人都可以为我阐明这一点吗?

4

1 回答 1

1

当键/值对被添加到字典中时,键被复制而值被保留。键被复制,因此它们不能被更改 - 字典的内部组织基于键。

这些值被保留,因为它们必须在字典中继续存在,但如果该值是可变类型,那么它可以被突变。例如,如果您创建一个对象字典,NSTextField则键和对象之间的关联NSTextField是固定的,但各个文本字段本身的内容可以更改。

看起来在您的代码中每次调用时都会[_mainTextField string]返回对同一对象的引用。 NSMutableString这意味着字典中的每个值都是对同一个可变对象的引用,并为您提供您所看到的行为。您可以通过复制内部使用的可变字符串更改[_mainTextField string]为返回一个来解决此问题;或通过复制使用返回的内容。如果 的目的是返回当前值的快照(无论其类型是什么 - 样本没有说明),则前者更好。NSString[[_mainTextField string] copy][_mainTextField string]_mainTextField

于 2013-06-14T16:13:39.193 回答