Контекст
У меня есть протокол Component
с объектом, соответствующим Category
в качестве ассоциированного типа. У меня также есть общий SwiftUI ComponentsView
, в котором я хотел бы использовать Category
данного Component
внутри ForEach
. Однако я получаю следующую ошибку компилятора:
Общая структура «ForEach» требует, чтобы «CCAllCases» соответствовала «RandomAccessCollection».
Код
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)
}
}
}
Вопрос
Насколько я понимаю, переменная allCases
в CaseIterable
возвращает Array
, который уже соответствует RandomAccessCollection
.
@JoakimDanielson Я этого не понимаю. Каждый тип, соответствующий категории, должен иметь переменную allCases типа Array. Почему компилятор этого не знает?
См. мой отредактированный комментарий выше, возвращаемый тип не должен быть массивом, это может быть набор, словарь или что-то еще. Внимательно прочитайте документацию, и вы это увидите.
В CaseIterable
AllCases определяется со значением по умолчанию:
associatedtype AllCases : Collection = [Self] where Self == Self.AllCases.Element
но это все, значение по умолчанию. В ComponentsView
:
struct ComponentsView<C: Component>: View {
var body: some View {
ForEach(C.C.allCases) { category in
Text(category.name)
}
}
}
Все, что видит компилятор, это Component
protocol Component {
associatedtype C: Category
}
у которого есть Category
то есть CaseIterable
:
protocol Category: Identifiable, CaseIterable {
var name: String { get }
}
Но нет информации о связанном с ним типе. Таким образом, это может быть массив или коллекция другого типа.
Добавление ограничения на Component.C
решает проблему:
protocol Component {
associatedtype C: Category where C.AllCases: RandomAccessCollection
}
Но компилятор этого не знает, он видит протокол CaseIterable и ничего больше. У протокола есть связанный тип, который соответствует Collection, поэтому возвращаемый тип allCases может быть множеством разных типов.