Hello, I have a problem with using struct in Dictionary. Please take a look at this code first.
import Foundation
struct COWStruct {
class COWStorageClass { }
var s = COWStorageClass()
mutating func mutateSomething() {
print(isKnownUniquelyReferenced(&self.s) ? "unique" : "not unique")
}
}
var dict: [Int: COWStruct] = [:]
dict[0] = COWStruct()
let keysArray = dict.keys.map { $0 }
for key in keysArray {
dict.values[dict.index(forKey: key)!].mutateSomething() // not unique
}
for key in keysArray {
dict[key]?.mutateSomething() // not unique
}
for key in keysArray {
dict[key]!.mutateSomething() // not unique
}
It’s simple. There is a struct with one mutating function to test that the storage property is uniquely referenced. This is used as a value in dict [Int: COWStruct]
As you see, all the mutating codes are failing to get the storage property uniquely referenced. They all print not unique
There's some discussion of this behaviour on this Stack Overflow Q&A:
The main issue is that currently Dictionary's subscript(_:) uses a getter + setter (in contrast to Array's subscript(_:) which uses a getter + addressor).
There are some workarounds to this however, such as using Dictionary's subscript(_:default:) which (as of Swift 4.1) uses an addressor, or temporarily removing the value you want to mutate before re-inserting it into the dictionary.
It would be really nice if we could find a way to make Dictionary's subscript(_:) work with addressors though.