Home > Software design >  Why does allCases Variable of Protocol conforming to CaseIterable not conform to RandomAccessCollect
Why does allCases Variable of Protocol conforming to CaseIterable not conform to RandomAccessCollect

Time:11-27

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
}
  • Related