[英]Storing KeyPaths in Dictionary/HashMap
哈希ReferenceWritableKeyPath
时遇到问题。 似乎 hash function 在散列密钥路径时也考虑了ReferenceWritableKeyPath
的通用属性。 我已经包含示例代码来说明为什么这是一个问题:
struct TestStruct<T> {
// This function should only be callable if the value type of the path reference == T
func doSomething<Root>(object: Root, path: ReferenceWritableKeyPath<Root, T>) -> Int {
// Do something
print("Non-optional path: \(path) \(path.hashValue)")
return path.hashValue
}
}
let label = UILabel()
let textColorPath = \UILabel.textColor
let testStruct = TestStruct<UIColor>()
let hash1 = testStruct.doSomething(object: label, path: \.textColor)
let hash2 = textColorPath.hashValue
print("Optional path: \(textColorPath) \(hash2)")
如果你运行上面的代码,你会注意到 hash1 和 hash2 是不同的,尽管它们是指向 UILabel 相同属性的路径。
发生这种情况是因为第一个ReferenceWritableKeyPath
的Value
是UIColor
,而第二个ReferenceWritableKeyPath
的Value
是Optional<UIColor>
我的项目需要将ReferenceWritableKeyPath
存储在字典中,以便关联的 object (UILabel) 的每个属性只有一个 keyPath。 由于哈希值不同,这意味着相同的路径将在字典中存储为 2 个不同的键。
有谁知道我可以让它工作的方法?
~提前谢谢
使textColorPath
也不是可选的,以匹配:
let textColorPath = \UILabel.textColor!
或明确说明类型:
let textColorPath: ReferenceWritableKeyPath<UILabel, UIColor> = \.textColor
潜在的问题是\.textColor
是一个隐式展开的可选而不是“真正的”可选。 在某些情况下,它被视为基础类型,而在其他情况下,它被提升为 Optional。 它是隐式展开的可选项的原因是因为将textColor
设置为 nil 是合法的。 但是您读取的值永远不会为零。
正如@Rob Napier 指出的那样,问题出在泛型类型本身。 我解决问题的方法是将doSomething
拆分为两个单独的方法:
func doSomething<Root>(object: Root, path: ReferenceWritableKeyPath<Root, T?>) -> Int {
// Do something
print("Non-optional path: \(path) \(path.hashValue)")
return path.hashValue
}
func doSomething<Root>(object: Root, path: ReferenceWritableKeyPath<Root, T>) -> Int {
// Do something
print("Non-optional path: \(path) \(path.hashValue)")
return path.hashValue
}
第一个将在T
是可选类型时调用,例如上面的示例(其中UIColor
可以为 nil)。 当 keyPath 指向非可选属性时,第二个被调用。 Swift 非常聪明,所以我想它能够找出调用哪个方法,尽管它们几乎有重复的标题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.