简体   繁体   中英

Does adding a key value pair to a dictionary change the pointer's address?

So I am working on a piece of code on IOS Swift, Xcode 6.2, and am trying to trace why changes in a dictionary do not perpetuate up callbacks. I started by printing the address of the dictionary along the way to see where the address changes, and I found the following lines of code to be the part where the

println("Address of grouped asset in 811 is " + EtaError.pointerToString(assetGroup!))
assetGroup![groupDid!] = Array<Asset>();
println("Address of grouped asset in 813 is " + EtaError.pointerToString(assetGroup!))

Note: asset group is a string->Asset array dictionary and EtaError.pointerToString is a function that returns the address of the given pointer, which is a separate function I have written.

Is assigning a new key-value pair supposed to change the address of a pointer to the dictionary?

Dictionaries in Swift are value, not reference, type like NSDictionary . Updates to the copy won't be reflected in the original. Here's a minimal example:

var a = ["name": "John", "location": "Chicago"]
var b = a

b["title"] = "developer"

print(a) // a does not contain the 'title' key
print(b)

You need to update the original after updating the copy. You can delve into stuffs like UnsafeMutablePointer<T> but it's a dark road down there.

Value Semantics of Dictionary

From your comment:

however the class from which I call this function to update a key-value pair does not reflect the change in

The updates to dictionaries won't be reflected in other parts of your code. Dictionary is a value type in Swift, which means it is copied upon every assignment, and each part of your code has its private copy of the value .

The change of the address is also interesting however.

Why is the Dictionary 's address changing?

The address changes because the underlying data structure of the Dictionary needs to be resized when you add values.

You can test it with the following simple code in a playground:

var dict = ["a":"b"]
print(unsafeAddressOf(dict))
// 0x00007ffc216278d0

dict["a"] = "c"    
print(unsafeAddressOf(dict))
// address remains: 0x00007ffc216278d0

dict["b"] = "f"
print(unsafeAddressOf(dict))
// new address: 0x00007ffc21705f40

dict["c"] = "f"
print(unsafeAddressOf(dict))
// address remains: 0x00007ffc21705f40

dict["d"] = "f"
print(unsafeAddressOf(dict))
// new address: 0x00007ffc21626db0

...

You will see that an address change will only occur when you add key/ value pairs, not when you modify an existing key.

Swift doubles the capacity of the dictionary upon copy, therefore, after the first copy, you can add two more values before the dictionary is copied again.

From the documentation:

The actual capacity will be the smallest power of 2 that's >= minimumCapacity.

If you initialize the dictionary with a sufficient capacity you will see that it won't be copied when you add values:

var dict = [String:String](minimumCapacity: 20)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM