NsDictionary setValue vs setObject

Can someone explain the difference on NSDixtuonary
setValue va setObject?

I’m guessing objects are objects that aren’t
NSString, number. Etc

How about setting NAArray’s

Thanks

I presume you mean NSMutableDictionary, and if you look at the documentation, the difference is explained pretty clearly.

My reading is that setObject:forKey: is the method which does the business of either adding a key-value pair to a mutable dictionary or changing the value associated with a key. The only limitation set on the ‘key’ parameter is that it must be a copiable object — presumably so that the key in the dictionary can be made a separate object from the parameter itself. But I can’t immediately see why anyone would want to use anything other than text. Only dictionaries whose keys are all text can be coerced to AppleScript records.

Dictionaries, arrays, and sets aren’t allowed to contain nil (usually represented by ‘missing value’ in ASObjC), so the ‘object’ parameter mustn’t be ‘missing value’. If it is, setObject:forKey: throws an error.

If a dictionary or an array is derived from an AppleScript record or list already containing ‘missing value’ values, the ‘missing values’ are represented in the result as instances of NSNull, for which there’s no equivalent in AppleScript. Coercing the dictionary or array back to record or list produces ‘missing values’ from the NSNull instances. So if you need to set a ‘missing value’ equivalent in a dictionary, it has to be passed as an NSNull instance:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set dict to current application's class "NSMutableDictionary"'s dictionaryWithDictionary:({a:"aardvark", b:"banana"})

set |null| to current application's class "NSNull"'s |null|() -- No connection with the unofficial AS keyword 'null'.
tell dict to setObject:(|null|) forKey:("b")
tell dict to setObject:(|null|) forKey:("c")
return dict as record -- {a:"aardvark", b:missing value, c:missing value}

setValue:forKey: is three system versions younger than setObject:forKey: and is essentially a “convenience” or “smart” version of it. If it’s used to add a key-value pair or change a value in a mutable dictionary, it calls setObject:forKey: to do the work. The difference is that if the ‘value’ parameter is nil (or AppleScript’s ‘missing value’), removeObjectForKey: is invoked instead to remove the key and its current value if they exist:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set dict to current application's class "NSMutableDictionary"'s dictionaryWithDictionary:({a:"aardvark", b:"banana"})

tell dict to setValue:(missing value) forKey:("b")
tell dict to setValue:(missing value) forKey:("c")
return dict as record -- {a:"aardvark"}

I’m just about to go away for a couple of days, so if Shane or anyone comments that the above’s a load of baloney, I’ll acknowledge it when I get back. :slight_smile:

In ASObjC, no, but in Objective-C there can be times when it makes sense to use other classes.

setValue:forKey: is actually defined in NSObject (twice!), so it’s inherited, but the collection classes override it with their own implementations. The setValue:forKey: method, plus valueForKey: are the basis of Key Value Coding, which is (partly) about being able to use strings for method calls.

Thanks, Shane. :slight_smile:

I’m not citing this as an example to follow, but just for fun, I decided to see if it was possible:

use framework "Foundation"
use scripting additions

set dict to current application's class "NSMutableDictionary"'s dictionaryWithDictionary:({a:"aardvark", b:"banana"})

tell dict to setObject:(0) forKey:(number)
tell dict to setObject:(null) forKey:("c")
return dict as record -- {b:"banana", c:null, a:"aardvark", number:0}

I should add in case anyone wonders, that the AppleScript type class null, despite the moniker, is not related to the NSNull value |null|().

:slight_smile: OTOH, asking for number of (dict as record) might not return what you expect :frowning:

Indeed, it’s not really related to anything. As I understand it, it’s there as a sort of placeholder should apps wish to implement it.