我正在尝试用字典测试复制。如果我正确地理解了我的书,当我们制作原始字典的副本时,新字典中的对象将仅引用原始字典中的那些元素(类似于数组的浅表副本)。在下面的示例中,我将字符串对象添加到字典中,然后复制字典并打印两个字典的结果。然后我改变字符串的值并再次打印两个字典。但是,结果与字符串的原始值相同。字典的最后一个印刷品不应该显示字符串的新值吗?
NSMutableString * phoneRef = [NSMutableString stringWithString:@"444"];
NSString * phoneKey = @"phone";
NSDictionary * myDict = [NSDictionary dictionaryWithObjectsAndKeys: phoneRef, phoneKey, nil];
NSMutableDictionary *dictCopy = [myDict mutableCopy];
NSLog(@"%@", myDict);
NSLog(@"%@", dictCopy);
phoneRef = [NSMutableString stringWithString:@"555"];
NSLog(@"%@", myDict);
NSLog(@"%@", dictCopy);
答案 0 :(得分:2)
我在评论中猜测答案,因为此刻我无法访问Mac,但这就是正在发生的事情。
将字符添加到字典时,字典会保留指向这些对象的指针。
执行此操作时:
phoneRef = [NSMutableString stringWithString:@"555"];
//or even just phoneRef = @"555";
您没有更改phoneRef
最初指向的内存位置的内容(您的词典指向的内存位置)。您正在更改phoneRef
指针的值,将其指向内存中包含字符串值@"555"
的新位置。
但是,字典仍然指向旧的内存位置,该位置仍包含@"444"
。
但是,使用这种方法:
[phoneRef setString:@"555"];
或者您直接在实例化对象phoneRef
(例如replaceOccurrencesOfString:withString:options:range:
或replaceCharactersInRange:withString:
等)上调用的任何其他方法,您实际上是在修改内存地址的内容phoneRef
实际指向的是setString:
。这些词典在技术上是100%完全未经修改的。它们只包含指向内存地址的指针(它们甚至不知道它们指向的是什么类型的对象,我不认为)。使用NSLog(@"Address of phoneRef: %p", &phoneRef);
方法,更改字典指向的内存地址的值。
为了更清楚地了解正在发生的事情,您可以使用以下内容打印指针的值(所有内容指向的内存地址):
phoneRef = [NSMutableString stringWithString:@"555"];
在[phoneRef setString:@"555"];
之前和之后以及{{1}}之前和之后抛出该行,以便更清楚地了解正在发生的事情。