How it works
TupleTableRowContent is the concrete row-content type that SwiftUI synthesizes when a table's rows builder lists more than one row. It plays the same role for tables that TupleView plays for views: the @TableRowBuilder gathers each TableRow you write into a single statically typed tuple, and TupleTableRowContent is what that aggregate becomes. You rarely name it yourself — it surfaces as the inferred TableRowContent of a Table whenever you supply several rows side by side, letting the compiler track each row's value type without erasing it.
Let @TableRowBuilder fold multiple rows into TupleTableRowContent
A trailing rows closure is a @TableRowBuilder, and when it contains several statements the builder wraps them into one TupleTableRowContent rather than requiring a container. In the example the three
TableRowlines in therows:block —TableRow(Person(name: "Ada", role: "Engineer")), the"Grace"row, and the"Alan"row — are combined into a single TupleTableRowContent value that becomes the table's row content.Match the row's RowValue to the table's element
Every TableRow carries a RowValue, and TupleTableRowContent preserves each one in its tuple so the table can render columns against them. Here each
TableRowwraps aPerson, which matchesTable(of: Person.self); the columnsTableColumn("Name", value: \.name)andTableColumn("Role", value: \.role)then read key paths on that samePersonvalue.Build static rows without ForEach
Reach for the tuple form when you have a small, fixed set of rows known at compile time — listing them directly produces TupleTableRowContent, whereas a dynamic collection would yield a ForEach-based row content instead. The example states
Ada,Grace, andAlanliterally, so noForEachis needed and each row keeps its own statically known position.Apply modifiers to the Table, not the tuple
TupleTableRowContent conforms to TableRowContent but is an internal aggregate, so you style and lay out the surrounding Table rather than the tuple itself. In the example
.padding()is applied to the wholeTable, while TupleTableRowContent quietly supplies the row data underneath.
TableRow(Person(name: "Alan", role: "Researcher")) line so only two rows remain, then add a fourth — the inferred TupleTableRowContent arity changes with each TableRow statement you add or remove.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 TupleTableRowContentDemo: View {
struct Person: Identifiable {
let id = UUID()
let name: String
let role: String
}
var body: some View {
Table(of: Person.self) {
TableColumn("Name", value: \.name)
TableColumn("Role", value: \.role)
} rows: {
TableRow(Person(name: "Ada", role: "Engineer"))
TableRow(Person(name: "Grace", role: "Admiral"))
TableRow(Person(name: "Alan", role: "Researcher"))
}
.padding()
}
}