How it works
DisclosureTableRow is a table row that displays a value and can expand to reveal a nested set of child rows beneath it. It brings the familiar disclosure-triangle affordance of an outline to the columnar world of Table, letting you present hierarchical data — categories and their members, a folder and its contents — without abandoning the aligned columns a table gives you. Reach for it inside a Table's rows builder whenever each top-level item owns a collection of sub-items that the reader should be able to fold away or drill into.
Construct the row from a parent value
The primary initializer takes the value the row represents and a
@TableRowBuilderclosure that produces the rows to show when the row is expanded. In the example,DisclosureTableRow(group)is handed each top-levelItem, so the parent occupies its own row across theNameandPricecolumns while its children stay tucked beneath the disclosure triangle.Supply the children in the row builder
The trailing closure is a row builder, not a view builder, so its contents must themselves be table rows. Here a nested
ForEach(group.children)emits aTableRow(child)for each sub-item, and those generated rows are what the disclosure triangle collapses and reveals.Let the children flow through the same columns
DisclosureTableRowdoesn't define its own layout — the parent and the disclosed children are rendered by the table's column definitions,TableColumn("Name", value: \.name)andTableColumn("Price", value: \.price). Because every row maps the sameItemproperties, the nestedAppleandBananarows stay aligned under their headers just likeFruitdoes.Provide stable identity for the rows
Disclosure rows participate in the same diffing as any table row, so the underlying value needs an identity. The example conforms
ItemtoIdentifiablewith aUUIDid, which lets the outerForEach(items)and the innerForEach(group.children)track each parent and child as the table expands or collapses.
children array, such as another Item(name: "Yogurt", price: "$1.10") under Dairy, and watch the new row appear beneath the Dairy disclosure triangle when it's expanded.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 DisclosureTableRowDemo: View {
struct Item: Identifiable {
let id = UUID()
let name: String
let price: String
var children: [Item] = []
}
let items = [
Item(name: "Fruit", price: "", children: [
Item(name: "Apple", price: "$1.20"),
Item(name: "Banana", price: "$0.80")
]),
Item(name: "Dairy", price: "", children: [
Item(name: "Milk", price: "$2.50")
])
]
var body: some View {
Table(of: Item.self) {
TableColumn("Name", value: \.name)
TableColumn("Price", value: \.price)
} rows: {
ForEach(items) { group in
DisclosureTableRow(group) {
ForEach(group.children) { child in
TableRow(child)
}
}
}
}
.padding()
}
}