I would like to have a Dictionary of Dictionaries. I'm coming from mostly a Python background, where I can simply allocate and assign a top-level key to be a new dictionary, then use a reference to that dictionary to update it no matter how deeply it is nested.
I am trying to do the same thing in Swift. I am using [NSObject: AnyObject]
because it must be bridgeable to NSDictionary
so I can store it in NSUserDefaults
.
Here is an example Playground:
import Cocoa
var foo = [NSObject: AnyObject]()
foo["aa_key"] = "aa_value"
println(foo)
foo["bb_key"] = [NSObject: AnyObject]()
println(foo)
if var bar = foo["bb_key"] as? [NSObject: AnyObject] {
bar["cc_key"] = "cc_value"
println("bar: \(bar)")
} else {
println("Could not get bb dictionary")
}
// bb_key is still an _empty_ dictionary in foo!
println("foo: \(foo)")
The resulting output in the console (not the playground) is:
[aa_key: aa_value]
[aa_key: aa_value, bb_key: { }]
bar: [cc_key: cc_value]
foo: [aa_key: aa_value, bb_key: { }]
I can see that in the section where the Optional result of the downcast is unwrapped into bar
, that assignments to the bar
Dictionary are correct. However, when I later print foo
, the changes have not made it.
It appears that bar is not a proper reference to the dictionary that is stored in foo["bb_key"]
. Why not?
In Swift all collection types are value types unlike reference types in Objective-C, that means the object in bar
is not the same object as in foo["bb_key"]
You have to reassign / update the value in foo["bb_key"]
var foo = [NSObject: AnyObject]()
foo["aa_key"] = "aa_value"
println(foo)
foo["bb_key"] = [NSObject: AnyObject]()
println(foo)
if var bar = foo["bb_key"] as? [NSObject: AnyObject] {
bar["cc_key"] = "cc_value"
foo.updateValue(bar, forKey: "bb_key")
println("bar: \(bar)")
} else {
println("Could not get bb dictionary")
}
// bb_key is still an _empty_ dictionary in foo!
println("foo: \(foo)")