[英]`Identifiable` conformance return type generic as variable
我正在嘗試從 Apple 的此示例構建OutlineGroup
: https://developer.apple.com/documentation/swiftui/outlinegroup
但是,我不想使用 static 類型,而是想使用符合我的協議的對象。 因此,如果在 swift 中可行的話,這個問題就更籠統了:
我有協議,可以為我提供來自各種對象的coworkers
和name
:
protocol CastProtocol {
var name: String { get }
var coworkers: [CastProtocol]? { get } // here will be the build error later
}
並以兩個模型為例:
class Actor: Identifiable, CastProtocol {
var id: Self { self }
var name: String { return "Chuck Norris" }
var coworkers: [CastProtocol]? {
return [
Director()
]
}
}
class Director: Identifiable, CastProtocol {
var id: Self { self }
var name: String { return "Gina Carey" }
var coworkers: [CastProtocol]? {
return [
Actor(),
Director(),
Actor()
]
}
}
所以到目前為止一切正常,但我需要確保我的CastProtocol
符合Identifiable
,因此將我的協議實現更改為:
protocol CastProtocol: Identifiable {
...
}
現在這產生了一個問題:
協議“CastProtocol”只能用作通用約束,因為它具有 Self 或關聯的類型要求
coworkers
中返回不是 static 類型,或者我應該 go 子類化?coworkers
可以包含Actor
或Director
associatedType 我認為不能使用協議從不符合其他協議。 語法protocol CastProtocol: Identifiable
並不意味着“CastProtocol 符合 Identifiable”。 它的意思是“為了符合 CastProtocol,一個類型也必須符合 Identifiable”。
但是,對於這個問題,不,您不能要求這樣做。 Identifiable
包括一個關聯的類型ID
。 考慮這段代碼:
let coworker in coworkers {
let id = coworker.id // What type is `id` here?
...
}
在這種情況下,Swift 無法分配單個類型類型id
。 有一天,他們可能會添加一個名為 Generalized Existential 的功能,該功能允許將id
推斷為Any where Self: Hashable
類型,但目前無法在 Swift 中表達。
但在你的情況下,它無論如何都無法工作。 說你可以做到這一點。 由於您已將標識符設置為 object 本身,因此系統最終需要評估Director == Actor
。 這在 Swift 中是不可能的。 那些不是同一類型。
相反,如果您真的希望 Cast 成員成為類,我懷疑您想要這個:
protocol CastMember: class {
var name: String { get }
var coworkers: [CastMember] { get } // Optional Arrays are almost always wrong
var id: ObjectIdentifer { get }
}
extension CastMember {
var id: ObjectIdentifier { ObjectIdentifier(self) }
}
// You can still put Identifiable here for [Actor] properties
class Actor: CastProtocol, Identifiable {
// ...
}
現在,這不會讓您將這些直接放入ForEach(actor.coworkers)
調用中,我認為這是您想要的。 就個人而言,我只是傳遞id: \.id
參數,但如果你經常這樣做,你當然可以通過擴展使它更好一點:
extension ForEach where Content : View, Data.Element == CastMember {
public init(_ data: Data, @ViewBuilder content: @escaping (Data.Element) -> Content) {
self.init(data, id: \.id, content: content)
}
}
注意Data.Element == CastMember
不是:
。 這適用於 CastMember 數組,而不是符合 CastMember 的事物數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.