TechnologiesSwiftUI

TableOutlineGroupContent struct

iOSmacOStvOSwatchOSvisionOS✓ renders

An opaque table row type created by a table's hierarchical initializers.

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.

  1. 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 FileItem is Identifiable and carries var children: [FileItem]? = nil, which is what lets the same struct describe both folders and the files nested beneath them.

  2. 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") and TableColumn("Size") definitions render item.name and item.size for top-level folders and their children alike, with no separate template per depth.

  3. Produce the rows with OutlineGroup and a children key path

    Placing an OutlineGroup in 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.

  4. 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 each row, so each FileItem the outline reaches becomes one column-aligned entry, parent or child.

  5. 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 for Documents and Photos, and the resulting row content composes into a single Table.

Try it — Add a third nested entry to one folder, for example a 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.

TableOutlineGroupContent.swift
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()
    }
}
Live preview
Name Size
Name Size
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →