TL; DR
Вам необходимо VStack
, HStack
, List
и т. Д. Вне каждого ForEach
.
Обновлено
Для второй части вашего вопроса вам нужно изменить свой ForEach, включив в него параметр id:
ForEach(self.ListeJoueurs[EquipName].indices, id: \.self)
Если данные не постоянны и число элементов может измениться, вам необходимо включитьid: \.self
, поэтому SwiftUI знает, куда вставить новые представления.
Пример
Вот пример кода, демонстрирующий работающий вложенный ForEach.Я составил модель данных, которая соответствует тому, как вы пытались ее назвать.
struct ContentView: View {
// You can ignore these, since you have your own data model
var ListeEquip: [Int] = Array(1...3)
var ListeJoueurs: [[String]] = []
// Just some random data strings, some of which are empty
init() {
ListeJoueurs = (1...4).map { _ in (1...4).map { _ in Bool.random() ? "Text" : "" } }
}
var body: some View {
VStack { // Added this
ForEach(self.ListeEquip.indices, id: \.self) { item in
VStack { // Added this
ForEach(self.ListeJoueurs[item].indices, id: \.self) { index in
if self.ListeJoueurs[item][index].isEmpty { // If string is blank
Text("Placeholder")
.foregroundColor(.red)
} else { // If string is not blank
Text(self.ListeJoueurs[item][index])
}
}
}.border(Color.black)
}
}
}
}
Объяснение
Вот что Документация Apple говорит о ForEach:
Структура, которая вычисляет представления по требованию из базовой коллекции [sic] идентифицированных данных.
Так что что-то вроде
ForEach(0..2, id: \.self) { number in
Text(number.description)
}
действительно просто сокращение для
Text("0")
Text("1")
Text("2")
Таким образом, ваш ForEach создает несколько представлений, но этот синтаксис для объявления представлений действителен только внутри представлений, таких как VStack, HStack, List, Group и т. Д. Техническая причина заключается в том, что эти представления имеютинициализация, которая выглядит как
init(..., @ViewBuilder content: () -> Content)
и что @ViewBuilder
совершает магию, которая допускает этот уникальный синтаксис.