我有一個帶有關聯值的列舉,我想將其用作 RxDataSources 中的一個專案。我嘗試通過將其符合 Hashable 來使其符合可識別性,如下所示
enum DriverHubWidget: Hashable, Identifiable {
static func == (lhs: DriverHubWidget, rhs: DriverHubWidget) -> Bool {
return lhs.hashValue == rhs.hashValue
}
var id: Int { hashValue }
case greetings(DriverHubGreetingsViewModel)
case scorecard(DriverHubScorecardSummary?, Error?)
case optOut
func hash(into hasher: inout Hasher) {
switch self {
case .greetings( _):
return hasher.combine(1)
case .scorecard( _, _):
return hasher.combine(2)
case .optOut:
return hasher.combine(3)
}
}
}
我通過簡單地為每個案例分配一個 Int 值來實作哈希函式。然后為了符合可識別,我添加了一個回傳hashValue的id屬性。這編譯得很好。
現在,當我嘗試使用它為節模型宣告型別別名時,如下所示
typealias WidgetSection = AnimatableSectionModel<String, DriverHubWidget>
它確實編譯并拋出錯誤,Type 'DriverHubWidget' does not conform to protocol 'IdentifiableType'
我不明白為什么它不起作用,當列舉符合 Hashable 和 Identifiable 時它編譯得很好,但是當使用時,一致性以某種方式無效是不是因為列舉的關聯值不是 Hashable?
uj5u.com熱心網友回復:
你混淆Identifiable了 Swift 內置協議IdentifiableType和 RxDataSource 庫中的協議。
你可以只符合IdentifiableType.
enum DriverHubWidget: Hashable, IdentifiableType {
var identity: Int {
hashValue
}
...
}
不過,你遵守的方式Hashable對我來說似乎很奇怪。您正在考慮列舉的兩個值相等,只要它們是相同的大小寫,而忽略它們的關聯值。也就是說,.greeting(x) == .greeting(y)會是真的。這似乎相當違反直覺。如果這確實是您想要的identity,您可能只想以identity這種方式實作:
var identity: Int {
switch self {
case .greetings( _):
return 1
case .scorecard( _, _):
return 2
case .optOut:
return 3
}
}
并Hashable通過實際考慮相關值來符合,或者根本不符合Hashable。
uj5u.com熱心網友回復:
(這不是一個完整的答案,但評論太長了。將其視為 Sweeper 已經說過的內容的附錄)
對于要成為的物件Identifiable,它們需要具有將它們與其他相關物件區分開來的穩定(即不隨時間變化)的身份概念。究竟哪種身份概念對您的目的有意義取決于您自己。正如檔案所述:
Identifiable 未指定身份的持續時間和范圍。
- 身份可以具有以下任何特征: 保證始終唯一,如 UUID。
- 每個環境永久唯一,例如資料庫記錄鍵。
- 在行程的生命周期中是唯一的,例如全域遞增整數。
- 在物件的生命周期內是唯一的,例如物件識別符號。
- 在當前集合中唯一,如集合索引。由協議的構造者和接收者來記錄身份的性質。
您可能不想忽略身份概念中的相關值。否則,您的代碼可能會嘗試將兩個物件視為相同,即使它們的關聯值不同。
在實踐中,這意味著
DriverHubGreetingsViewModel,DriverHubScorecardSummary也需要符合Identifiable. 您的Error?關聯值,您可能希望將其變為(Error & Identifiable)?*您無法精細化 to 的實作
id,hashValue因為哈希值(按設計)是不可預測的。完全有可能您的所有三個案例最終都具有相同的 id(如果散列以 1、2 和 3 的散列全部沖突的方式播種,則會發生這種情況)
另一個注意事項:有一個可選模型,后跟一個可選錯誤是 Swift 中的代碼異味。這是來自 Objective C 的保留,其型別系統缺乏一種輕量級的方式來表達一種或另一種型別的值(“或”或“和”型別)。Swift 支持具有關聯值的列舉(您已經在使用一個!),它甚至可以是通用的。標準庫中已經為您內置了一個:Result<Success, Failure>
因此case scorecard(DriverHubScorecardSummary?, Error?),我建議:
case scorecard(Result<DriverHubScorecardSummary, Error & Identifiable>)
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/435783.html
標籤:迅速 rxdatasources 可识别的 快速散列
下一篇:使用正則運算式從URL中提取資訊
