TechnologiesSwiftUI

TableColumnCustomization struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A representation of the state of the columns in a table.

How it works

TableColumnCustomization is a value type that captures the user-driven state of a table's columns — their order, and which ones are hidden or shown. You hold it in your own storage and bind it to a Table so that the column layout a person arranges by dragging headers or toggling visibility survives across redraws and can be persisted or reset programmatically. Reach for it whenever a Table should remember how the reader rearranged it, rather than snapping back to the columns' declared order on every update.

  1. Store the customization as observable state

    TableColumnCustomization is generic over the table's row type, so you declare a single instance parameterized to your data and keep it where SwiftUI can observe writes to it. In the example it lives as @State private var customization = TableColumnCustomization<Person>(), an empty value that represents the default, unmodified layout until the table mutates it.

  2. Bind it to the table with columnCustomization:

    A Table accepts the customization through its columnCustomization: parameter as a binding, giving the table read-and-write access to the stored layout. Passing $customization to Table(people, columnCustomization: $customization) is what lets header drags and the column-visibility menu flow back into your state instead of being lost.

  3. Identify each column with customizationID()

    TableColumnCustomization tracks columns by a stable string key, so every column the user can reorder or hide must declare one with the .customizationID() modifier. The .customizationID("name") and .customizationID("role") tags on the two TableColumn values are the identifiers under which their order and visibility are recorded; a column without an ID can't participate in customization.

  4. Read and edit the recorded state

    Because it is an ordinary value, you can inspect or drive the layout yourself between renders — querying or setting a column's visibility by its customization ID, or assigning a fresh TableColumnCustomization<Person>() to restore the declared defaults. The customization value is the single source of truth the Table consults each time it lays out its columns.

Try it — Add a third column such as TableColumn("ID", value: \.id.uuidString).customizationID("id"), run it, drag the headers to reorder them, and watch the new arrangement stick because it's recorded in customization.

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.

TableColumnCustomization.swift
struct TableColumnCustomizationDemo: View {
    struct Person: Identifiable {
        let id = UUID()
        let name: String
        let role: String
    }

    @State private var customization = TableColumnCustomization<Person>()

    private let people = [
        Person(name: "Ada Lovelace", role: "Engineer"),
        Person(name: "Alan Turing", role: "Designer")
    ]

    var body: some View {
        Table(people, columnCustomization: $customization) {
            TableColumn("Name", value: \.name)
                .customizationID("name")
            TableColumn("Role", value: \.role)
                .customizationID("role")
        }
        .padding()
    }
}
Live preview
Name Role Ada Lovelace Engineer Alan Turing Designer
Name Role Ada Lovelace Engineer Alan Turing Designer
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →