How it works
TableColumnForEach generates a variable number of table columns from a collection of data, letting you build a Table whose column set isn't known until runtime. Inside a table's column builder you normally list each TableColumn by hand, but when the columns themselves are data-driven you reach for TableColumnForEach to produce one column per element. It plays the same role for columns that ForEach plays for rows, so the table's shape can scale with your model instead of being hard-coded.
Place it inside the Table column builder
TableColumnForEach is a column-builder content type, so it belongs in the closure you pass to
Table, alongside fixedTableColumndeclarations. In the example it sits afterTableColumn("Name", value: \.name), expanding into one column for each subject without disturbing the static name column.Supply the data and an identity
The initializer takes a collection plus an
idkey path that uniquely identifies each element, mirroringForEach. Here it iteratessubjects.indiceswithid: \.self, so each integer index becomes the stable identity for a generated column.Build one column per element in the trailing closure
The trailing closure receives a single element and must return the
TableColumnto create for it. The example binds the index asiand returnsTableColumn(subjects[i]), giving every subject its own titled column.Drive each column's cells from the row value
Because each generated column is an ordinary
TableColumn, its content closure still receives the table's row value. Capturingilets the cell readstudent.scores[i], so columnishows each student's score for that subject viaText("\(student.scores[i])").
subjects array and add a matching fourth score to each Student in students to watch TableColumnForEach grow the table by a whole new column.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct TableColumnForEachDemo: View {
struct Student: Identifiable {
let id = UUID()
let name: String
let scores: [Int]
}
let subjects = ["Math", "Science", "Art"]
let students = [
Student(name: "Ava", scores: [92, 85, 78]),
Student(name: "Leo", scores: [88, 91, 95])
]
var body: some View {
Table(students) {
TableColumn("Name", value: \.name)
TableColumnForEach(subjects.indices, id: \.self) { i in
TableColumn(subjects[i]) { student in
Text("\(student.scores[i])")
}
}
}
.padding()
}
}