Where's the difference between setObject:forKey: and setValue:forKey: in NSMutableDictionary?
Asked Answered
R

4

156

When looking at the documentation, I hardly see any big difference. Both "value" and "object" are of type id, so can be any object. Key is once a string, and in the other case an id. One of them seems to retain the object, and the other don't. What else? Which one is for what case?

Rubstone answered 8/8, 2009 at 18:57 Comment(1)
possible duplicate of Objective-C: What's the Difference between objectForKey and valueForKey?Aboriginal
F
167

setValue:forKey: is part of the NSKeyValueCoding protocol, which among other things, lets you access object properties from the likes of Interface Builder. setValue:forKey: is implemented in classes other than NSDictionary.

setObject:forKey: is NSMutableDictionary's reason to exist. Its signature happens to be quite similar to setValue:forKey:, but is more generic (e.g. any key type). It's somewhat of a coincidence that the signatures are so similar.

What adds to the confusion is that NSMutableDictionary's implementation of setValue:forKey: is equivalent to setObject:forKey: in most cases. In other classes, setValue:forKey: changes member variables. In NSMutableDictionary, it changes dictionary entries, unless you prefix the key with a '@' character -- in which case it modifies member variables.

So, in a nutshell, use setObject:forKey: when you need to work with dictionary keys and values, and setValue:forKey: in the rarer cases where you need to tackle KVP.

EDIT: and oh, it looks like this has been asked and answered before: Difference between objectForKey and valueForKey?

Fukien answered 8/8, 2009 at 19:9 Comment(5)
that question is not exactly the same. it is about the getter methods, whereas this question is about the setter methodsKaveri
What do you mean by "In NSMutableDictionary, it changes dictionary entries, unless you prefix the key with a '@' character -- in which case it modifies member variables." What member variables? Also maybe you can comment on stackoverflow.com/questions/5755917 ? Thanks.Jalopy
just for completeness, setObject:forKey will raise (exception) if object is nil. Will setValue:forKey behave the same, or will it remove existing object from dictionary when setting nil for key?Claptrap
Great answer. Really. for completeness though, it would be nice to mention that (on NSMutableDictionary at least) setValue:forKey: tolerates nil values, and removes the entry - while setObject:forKey: will throw exception and crash when handed nil values.Claptrap
In general, I recommend to use the modern Objective-C Syntax with NSMutableDictionary which completely avoids the confusion: ` NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init]; myDict[myKey] = myValue; `Treva
K
86

Another difference is that if you give a nil value to setValue:forKey:, it removes the key from the dictionary if it exists, otherwise does nothing. But if you give a nil value to setObject:forKey:, it raises an exception.

Kaveri answered 16/2, 2011 at 2:21 Comment(2)
This is super useful to know. I had otherwise written my own category on NSMutableDictionary to accomplish exactly this!. ThanksKnocker
Another difference is with objective-c subscripting, you can write dic[key] = value; to support removing the key if value is nil. Subscripting is generally a better approach than setValue:forKey: to accomplish this.Decumbent
H
11

-setValue:forKey: just send -setObject:forKey: to the receiver, unless the value is nil, in which case send -removeObjectForKey.

Dead simple.

Hulse answered 2/9, 2016 at 9:55 Comment(1)
oh you're right, bro. Sorry about that. It's documented here: developer.apple.com/reference/foundation/nsmutabledictionary/…Spaak
C
4

anObject — The value for key. The object receives a retain message before being added to the NSDictionary. This value must not be nil.

aKey — The key for value. The key is copied (using copyWithZone:; keys must conform to the NSCopying protocol). The key must not be nil.

value — The value for key.

key — The key for value. Note that when using key-value coding, the key must be a string (see “Key-Value Coding Fundamentals”).

Cordate answered 17/2, 2011 at 12:0 Comment(1)
Thanks for giving the atual reason why setObject:forKey: raises an exception. @CordateScandal

© 2022 - 2024 — McMap. All rights reserved.