Reputation: 75
I have a behavior question, I have a dictionary [String:AnyObject] And I would like to implement a update method, so I use
otherDictionary.forEach { thisDictionary.updateValue($1, forKey: $0) }
But I would like to know if the update of AnyObject just erase the old value and replace with the new one, or if that browse the entire graph that could be behind AnyObject (Complex objects for example) If anyone have the answer it could be awesome!
Upvotes: 2
Views: 237
Reputation: 154583
Since AnyObject
stores a reference to an instance of a class
, then what is stored as the value of your dictionaries is just a reference counted pointer to the instance of a class.
When you call let oldObject = thisDictionary.updateValue(newObject, forKey: foo)
, updateValue
replaces the reference that was being held in the dictionary with the one you pass in, and it returns the previously held object.
In your case, you are not capturing that return value, so Swift (using ARC: Automatic Reference Counting) will decrement the reference to the old object, and if that is the last reference in your app, it will free that object.
Since the values being updated are references, any changes you make to the object instances in the original dictionary would also be seen in the new dictionary and vice versa because they are just two references to the same object in memory.
Consider this example which creates dictionaries of Person
objects:
class Person: CustomStringConvertible {
var name: String
var age: Int
var description: String { return "\(name)-\(age)" }
init(name: String, age: Int) {
self.name = name
self.age = age
}
deinit {
print("\(self) was freed")
}
}
var otherDictionary: [String: AnyObject] = ["Fred": Person(name: "Fred", age: 25), "Wilma": Person(name: "Wilma", age: 24)]
var thisDictionary: [String: AnyObject] = ["Wilma": Person(name: "Smith", age: 86), "Barney": Person(name: "Barney", age: 26)]
otherDictionary.forEach { thisDictionary.updateValue($1, forKey: $0) }
print(thisDictionary)
print(otherDictionary)
(otherDictionary["Fred"] as? Person)?.age = 45
(thisDictionary["Wilma"] as? Person)?.name = "Flintstone"
print(thisDictionary)
print(otherDictionary)
Output:
Smith-86 was freed ["Wilma": Wilma-24, "Barney": Barney-26, "Fred": Fred-25] ["Wilma": Wilma-24, "Fred": Fred-25] ["Wilma": Flintstone-24, "Barney": Barney-26, "Fred": Fred-45] ["Wilma": Flintstone-24, "Fred": Fred-45]
In line 1 of the output, we see that Person(name: "Smith", age: 86)
was freed when the object was replaced in the Wilma
key in thisDictionary
.
In lines 4 and 5 of the output, we see that both "Wilma"
and "Fred"
have been updated in both dictionaries since each dictionary references the same objects.
Note: Since you are not capturing the value returned by updateValue(_:forKey:)
, so you can write your code as:
otherDictionary.forEach { thisDictionary[$0] = $1) }
Upvotes: 2