Context
I have a protocol Component
with an Object conforming to Category
as its associated type. I also have a generic SwiftUI ComponentsView
, in which I'd like to use the Category
of the given Component
inside a ForEach
. However, I get the following Compiler Error:
Generic struct 'ForEach' requires that 'C.C.AllCases' conform to 'RandomAccessCollection'
Code
protocol Component {
associatedtype C: Category
}
protocol Category: Identifiable, CaseIterable {
var name: String { get }
}
struct ComponentsView<C: Component>: View {
var body: some View {
ForEach(C.C.allCases) { category in
Text(category.name)
}
}
}
Question
- What causes the Compiler Error and how can I solve it?
From my understanding, the allCases
variable of CaseIterable
returns an Array
, which already conforms to RandomAccessCollection
.
CodePudding user response:
In CaseIterable
AllCases is defined with a default value:
associatedtype AllCases : Collection = [Self] where Self == Self.AllCases.Element
but that's all it is, a default value. In ComponentsView
:
struct ComponentsView<C: Component>: View {
var body: some View {
ForEach(C.C.allCases) { category in
Text(category.name)
}
}
}
All the compiler sees is a Component
protocol Component {
associatedtype C: Category
}
that has a Category
that is CaseIterable
:
protocol Category: Identifiable, CaseIterable {
var name: String { get }
}
But there is no information about its associated type. So, it could be an array, or it could be another type of collection.
Adding a constraint on Component.C
solves the issue:
protocol Component {
associatedtype C: Category where C.AllCases: RandomAccessCollection
}