微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Dictionary/HashMap 中存储 KeyPath

如何解决在 Dictionary/HashMap 中存储 KeyPath

我在对 ReferenceWritableKeyPath 进行哈希处理时遇到问题。哈希函数似乎在对密钥路径进行哈希处理时也考虑了 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 相同属性的路径。

发生这种情况是因为第一个 ReferenceWritableKeyPathValueUIColor,而第二个 ReferenceWritableKeyPathValueOptional<UIColor>

我的项目要求将 ReferenceWritableKeyPath 存储在字典中,以便关联对象 (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,T>) -> Int {
    // Do something
    print("Non-optional path:   \(path)                    \(path.hashValue)")
    return path.hashValue
}

第一个将在 T 是可选类型时被调用,例如在上面的示例中(其中 UIColor 可以为零)。当 keyPath 指向一个非可选属性时,第二个被调用。 Swift 非常聪明,所以我猜它能够找出调用哪个方法,尽管它们几乎有重复的标头。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。