Trygve
Trygve

Reputation: 1387

Does valueForKey: NSMutableDictionary use copy for NSStrings?

I have an NSMutableDictionary with a dozen keys, each key refers to an NSString value. If I call [myDictionary valueForKey:@"abc"] I will get an NSString object.

Is this NSString copied?

As there is no @property declaration, what happens with this retrieval of the string? I assume I get a copy. Is it any different with a NSMutableString?

My purpose is that I have an array of NSDictionaries. I call valueForKey on the array to get all the @"abc" keys from the collection of dictionaries. Thus I now have an array of NSStrings.

I need to pass that array to an NSOperation on a background thread. Thus, the NSStrings need to be copies so that modifying the dictionaries later will not cause the ones passed to the NSOperation to get changed.

Upvotes: 0

Views: 294

Answers (2)

James Bucanek
James Bucanek

Reputation: 3439

NSDictionary keys are copied when set. In the code dictionary[key] = value the key object is copied, and the dictionary retains the copy. The value object is not copied; the caller and the dictionary share a reference to the same object.

When retrieving keys or object, there is no copying. dictionary.allKeys returns an array of the key objects in the dictionary, not copies. Similarly, dictionary[key] returns a reference to the value for key in the dictionary.

And just so you know, the @property (copy) only applies when setting the value. ObjC getters never copy objects, unless it is specifically documented that way or you write your own so it does that.

Similarly, and to get to your question, key-value method use the same underlaying rules for that property. So -setValue:forKey:, -setValue:forKeyPath:, -valueForKey:, -valueForKeyPath: etc. will get or set the proper value as if you accessed the property directly. In other words, if the value is copied when the property is set, -setValue:forKeyPath: will copy the value. If an accessor does not copy the value, then -valueForKey: will not copy the value.

Upvotes: 1

Willeke
Willeke

Reputation: 15589

From the documentation of -[NSDictionary valueForKey:]:

If key does not start with “@”, invokes objectForKey:. If key does start with “@”, strips the “@” and invokes [super valueForKey:] with the rest of the key.

From the documentation of -[NSMutableDictionary setObject:forKey:]:

If aKey already exists in the dictionary, anObject takes its place.

valueForKey: does objectForKey: and does not copy the object. setObject:forKey: replaces the object, it does not modify the object. If you do

[mutableDictionary setObject:@"klm" forKey:@"abc"];
a = [mutableDictionary valueForKey:@"abc"];
[mutableDictionary setObject:@"xyz" forKey:@"abc"];

now a is the old value @"klm".

Upvotes: 1

Related Questions