TechnologiesSwiftUI

DocumentGroup struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A scene that enables support for opening, creating, and saving documents.

How it works

A DocumentGroup is a scene that builds a document-centric app around a single document type, wiring your editor view into the platform's open, save, and file-management machinery for you. Instead of managing windows, file URLs, and serialization by hand, you describe how to read and write your model and how to display it, and SwiftUI provides the New, Open, Save, and Revert commands, the document browser, and per-document windows or tabs. Reach for it when each window of your app edits one user-owned file — a text editor, drawing app, or spreadsheet — rather than presenting a single fixed interface.

  1. Conform your model to a document protocol

    DocumentGroup edits a type that conforms to FileDocument (or ReferenceFileDocument), which declares the file formats it reads through readableContentTypes and implements init(configuration:) to load and fileWrapper(configuration:) to save. In the editor, the document's contents are what the view binds to and mutates — here the editable string surfaced through the TextEditor's text binding stands in for that document state.

  2. Create the scene with newDocument and an editor closure

    Declare DocumentGroup(newDocument:editor:) in your app's body, passing an initializer that produces a fresh, empty document for the New command and a closure that builds the editing UI. The closure receives a configuration whose document binding you hand to your view — the role played by DocumentGroupDemo, whose body lays out the editing surface for one open file.

  3. Bind the editor to the open document

    The editor closure's FileDocumentConfiguration exposes a document property as a binding, so edits flow straight back into the model that DocumentGroup tracks for dirty state and autosave. In the example this is the $text binding driving TextEditor(text:); in a real document app you would instead bind to the document's own fields, and DocumentGroup marks the file modified as the user types.

  4. Let the scene supply file commands and windows

    Because DocumentGroup is a Scene, the system attaches the standard File menu (New, Open, Save, Duplicate, Revert) and opens each document in its own window on macOS or its own browser-backed scene on iOS — no per-window code required. Your view, like the VStack of Label and TextEditor shown here, only renders the contents of the currently focused document.

  5. Choose viewing versus editing initializers

    Use DocumentGroup(newDocument:editor:) for read-write apps, or DocumentGroup(viewing:viewer:) when documents are presented read-only. For class-based models that need explicit save semantics, pair ReferenceFileDocument with the matching initializer so DocumentGroup knows when to take a snapshot for writing rather than autosaving the value type.

Try it — Change the initial @State text from "Untitled.txt" to a multi-line string so you can see the bound TextEditor scroll, mirroring how a DocumentGroup editor reflects the contents of a larger open document.

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.

DocumentGroup.swift
struct DocumentGroupDemo: View {
    @State private var text = "Untitled.txt"
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Label("Document", systemImage: "doc.text")
                .font(.headline)
            TextEditor(text: $text)
                .frame(height: 120)
                .border(.secondary)
        }
        .padding()
    }
}
Live preview
Document Untitled.txt
Document Untitled.txt
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →