我目前正在读从objc.io优秀高级斯威夫特的书,我运行到的东西,我不明白斯威夫特语义。关于字典访问
如果运行在操场下面的代码,你会发现,修改包含在字典中的结构时,副本由下标访问制造,但随后便出现在字典中的原始值被替换复制。我不明白为什么。究竟发生了什么?
另外,有没有办法避免复制?根据这本书的作者,没有,但我只是想确定。
import Foundation
class Buffer {
let id = UUID()
var value = 0
func copy() -> Buffer {
let new = Buffer()
new.value = self.value
return new
}
}
struct COWStruct {
var buffer = Buffer()
init() { print("Creating \(buffer.id)") }
mutating func change() -> String {
if isKnownUniquelyReferenced(&buffer) {
buffer.value += 1
return "No copy \(buffer.id)"
} else {
let newBuffer = buffer.copy()
newBuffer.value += 1
buffer = newBuffer
return "Copy \(buffer.id)"
}
}
}
var array = [COWStruct()]
array[0].buffer.value
array[0].buffer.id
array[0].change()
array[0].buffer.value
array[0].buffer.id
var dict = ["key": COWStruct()]
dict["key"]?.buffer.value
dict["key"]?.buffer.id
dict["key"]?.change()
dict["key"]?.buffer.value
dict["key"]?.buffer.id
// If the above `change()` was made on a copy, why has the original value changed ?
// Did the copied & modified struct replace the original struct in the dictionary ?
当在Swift 3中突变字典KV对时,(现今)惯用的remove-mutate-replace操作的替代(以及同样常见的)实现是使用['removeValue(forKey:)'](https:/ /developer.apple.com/documentation/swift/dictionary/1641348-removevalue)方法执行联合存在检查和删除操作,而不是单独执行这些操作。例如。 'if var value = dict.removeValue(forKey:“key”){/ * mutate value并重新插入* /}'。一如既往的好答案,有趣的是你对新的Dictionary.Values集合的调查。 – dfri
@dfri啊,是的,非常好的一点!我已经编辑了我的答案:) – Hamish
我刚刚注意到,似乎目前副本和随后的'nil'赋值替代可能会产生(直接的'removeValue(forKey :))调用相比(最小?)开销,作为先前的选择,在明确地复制该值之后[[貌似也调用'removeValue(forKey :)),但放弃了'nil' assigment的结果](https://github.com/apple/swift/blob/master /stdlib/public/core/HashedCollections.swift.gyb#L1982)。但也许这是在发布版本中优化:) – dfri