How it works
TableOutlineGroupContent is the table-row content that SwiftUI synthesizes when you nest an OutlineGroup inside a Table's rows builder, letting a single table present hierarchical, expandable data instead of a flat list. You rarely name this type yourself; it is the conformance that makes an OutlineGroup behave as valid TableRowContent, so each parent row gains a disclosure triangle and its descendants render under the same columns. Reach for it whenever your model is a tree, such as a file system or an org chart, and you want the rows to expand and collapse in place while staying aligned to the table's columns.
Give the table a recursive, identifiable row type
TableOutlineGroupContent walks a tree by following each element's optional children, so the row model must be Identifiable and expose a child collection of its own type. Here
FileItemisIdentifiableand carriesvar children: [FileItem]? = nil, which is what lets the same struct describe both folders and the files nested beneath them.Declare columns once for the whole hierarchy
The columns defined in the Table's content builder apply uniformly to every level the outline produces, so parents and descendants share one layout. The
TableColumn("Name")andTableColumn("Size")definitions renderitem.nameanditem.sizefor top-level folders and their children alike, with no separate template per depth.Produce the rows with OutlineGroup and a children key path
Placing an
OutlineGroupin the rows builder is what yields TableOutlineGroupContent: the group reads the tree through a key path and emits a disclosable row for each node.OutlineGroup(item, children: \.children)tells SwiftUI to descend along\.children, automatically adding the expand and collapse control to any row that has them.Map each node to a TableRow inside the group's builder
Within the OutlineGroup builder you turn every visited node into a row, and that row is what TableOutlineGroupContent positions at the correct indentation. The closure returns
TableRow(row)for eachrow, so eachFileItemthe outline reaches becomes one column-aligned entry, parent or child.Drive multiple roots through ForEach
TableOutlineGroupContent represents one rooted hierarchy, so to show several top-level trees you iterate and emit one OutlineGroup per root. The
ForEach(items)loop creates a separate outline forDocumentsandPhotos, and the resulting row content composes into a single Table.
FileItem(name: "Archive.zip", size: "5 MB") inside Documents's children, then run and toggle that folder's disclosure triangle to watch TableOutlineGroupContent insert and remove the descendant rows under the same columns.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 TableOutlineGroupContentDemo: View {
struct FileItem: Identifiable {
let id = UUID()
var name: String
var size: String
var children: [FileItem]? = nil
}
let items = [
FileItem(name: "Documents", size: "--", children: [
FileItem(name: "Resume.pdf", size: "82 KB"),
FileItem(name: "Notes.txt", size: "4 KB")
]),
FileItem(name: "Photos", size: "--", children: [
FileItem(name: "Trip.jpg", size: "2.1 MB")
])
]
var body: some View {
Table(of: FileItem.self) {
TableColumn("Name") { item in
Text(item.name)
}
TableColumn("Size") { item in
Text(item.size)
}
} rows: {
ForEach(items) { item in
OutlineGroup(item, children: \.children) { row in
TableRow(row)
}
}
}
.padding()
}
}