Reputation: 3095
I'm trying to test out copying with a dictionary. If I understood my book correctly, when we make a copy of the original dictionary, then the objects in the new dictionary will just reference those elements from the original dictionary (similar to a shallow copy of an array). In my example below, I add a string object to a dictionary then copy the dictionary and print the results of both dictionaries. Then I change the value of the string and print both dictionaries again. However, the results are the same as the original value of the string. Shouldn't the last print of the dictionaries show the new value of the string?
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);
Upvotes: 0
Views: 85
Reputation: 62062
I was guessing at the answer in the comments since I don't have access to a Mac at this moment, but here's what's happening.
When you add objects to a dictionary, the dictionary is keeping the pointers to those objects.
When you do this:
phoneRef = [NSMutableString stringWithString:@"555"];
//or even just phoneRef = @"555";
You're not changing the contents of the memory location that phoneRef
originally pointed to (the memory location your dictionaries point to). You're changing the value of your phoneRef
pointer, pointing it to a new location in memory that contains the string value @"555"
.
The dictionaries, however, are still pointing to the old memory location, which still contains @"444"
.
HOWEVER, using this method:
[phoneRef setString:@"555"];
Or any other method you call directly on the instantiated object, phoneRef
(such as replaceOccurrencesOfString:withString:options:range:
, or replaceCharactersInRange:withString:
, etc), you're actually modifying the contents of the memory address that phoneRef
was actually pointing to. The dictionaries technically are 100% completely unmodified. They only contain pointers to memory addresses (they don't even know what kind of object they point to, I don't think). Using the setString:
method, you change the value at the memory address the dictionaries were pointing to.
To get a more clear picture of what's going on, you can print the value of the pointers (the memory address that everything is pointing to) using something like this:
NSLog(@"Address of phoneRef: %p", &phoneRef);
Throw that line in before and after phoneRef = [NSMutableString stringWithString:@"555"];
and before and after [phoneRef setString:@"555"];
to see more clearly what's going on.
Upvotes: 2