对于结构体,Swift 会自动为我们合成 hashValue。所以我很想用它来符合可识别性。
我知道hashValue是多对一的,但ID必须是一对一的。然而,哈希冲突非常罕见,而且我相信在我死之前我的应用程序很可能永远不会发生这种情况。
我想知道除了碰撞之外还有其他问题吗?
这是我的代码:
public protocol HashIdentifiable: Hashable & Identifiable {}
public extension HashIdentifiable {
var id: Int {
return hashValue
}
}
Run Code Online (Sandbox Code Playgroud)
使用hashValueforid是一个坏主意!
例如你有 2 个结构
struct HashID: HashIdentifiable {
var number: Int
}
struct NormalID: Identifiable {
var id = UUID()
var number: Int
}
Run Code Online (Sandbox Code Playgroud)
何时number更改:
HashID也会id被改变,让人SwiftUI认为这是全新的物品,旧的已经消失了NormalID保持id不变,所以SwiftUI知道该项目仅修改了其属性SwiftUI让知道发生了什么非常重要,因为它会影响动画、性能……这就是为什么使用hashValueforid会让你的代码看起来很糟糕,你应该远离它。
小智 1
\n\n我想知道除了碰撞之外还有其他问题吗?
\n
是的,很多。
\n例如,用这个\xe2\x80\xa6
\nstruct ContentView: View {\n @State private var toggleData = (1...5).map(ToggleDatum.init)\n\n var body: some View {\n List($toggleData) { $datum in\n Toggle(datum.display, isOn: $datum.value)\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nstruct ToggleDatum: Identifiable & Hashable {\n var value: Bool = false\n var id: Int { hashValue }\n var display: String { "\\(id)" }\n\n init(id: Int) {\n // Disregard for now.\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nstruct ToggleDatum: Identifiable & Hashable {\n var value: Bool = false\n var id: Int { hashValue }\n let display: String\n\n init(id: Int) {\n self.display = "\\(id)"\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n然而,虽然使用哈希值作为标识符是不可接受的,但可以采取相反的做法:使用标识符进行哈希,只要您知道 ID 对于使用集来说是唯一的。
\n/// An `Identifiable` instance that uses its `id` for hashability.\npublic protocol HashableViaID: Hashable, Identifiable { }\n\n// MARK: - Hashable\npublic extension HashableViaID {\n func hash(into hasher: inout Hasher) {\n hasher.combine(id)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nstruct ToggleDatum: HashableViaID {\n var value: Bool = false\n let id: Int\n var display: String { "\\(id)" }\n\n init(id: Int) {\n self.id = id\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n该协议非常适合Equatable类,因为类已经有一个可供使用的默认 ID 。
extension Identifiable where Self: AnyObject {\n public var id: ObjectIdentifier {\n return ObjectIdentifier(self)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n我并不建议在此示例中使用引用类型,但它看起来像这样:
\npublic extension Equatable where Self: AnyObject {\n static func == (class0: Self, class1: Self) -> Bool {\n class0 === class1\n }\n}\n\nclass ToggleDatum: HashableViaID {\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2136 次 |
| 最近记录: |