TechnologiesSwiftUIDocuments

FileDocumentConfiguration struct

iOSmacOStvOSwatchOSvisionOS✓ renders

The properties of an open file document.

How it works

FileDocumentConfiguration is the value SwiftUI hands a document scene so its content view can read and write the open file. When you build a document app with DocumentGroup, the framework wraps your FileDocument in this structure and gives you a binding to the live document along with metadata about where it lives on disk and whether it may be changed. Reach for it whenever a view needs to edit the document's model directly or react to the file's location and editability, rather than just displaying a static copy.

  1. Bind to the live document through document

    The document property exposes the open file's model so edits flow straight back into the document SwiftUI is managing. Because it is projected as a binding, you reach a field of the model with the dollar projection — here config.$document.text feeds the text binding directly into a TextEditor, so typing mutates the document in place.

  2. Read the file's location from fileURL

    fileURL is an optional URL giving the document's on-disk location, or nil for a new, unsaved document. The example surfaces it for display with config.fileURL?.lastPathComponent ?? "Untitled", falling back to a placeholder when the file has no location yet.

  3. Check write access with isEditable

    The isEditable Boolean reports whether the document can currently be modified, which lets a view adapt its interface for read-only contexts such as a locked or shared file. Here it drives a status label via config.isEditable ? "Editable" : "Read-only".

  4. Supply the FileDocument the configuration wraps

    FileDocumentConfiguration is generic over a FileDocument, and the conforming type defines how bytes turn into a model and back. The example's TextFile declares readableContentTypes, decodes configuration.file.regularFileContents in its ReadConfiguration initializer, and serializes through fileWrapper(configuration:) so the structure has something concrete to expose.

  5. Obtain it from the document scene

    In a real app you do not construct this yourself; DocumentGroup builds it per open file and passes it to your content view. The demo instead stands one up directly with FileDocumentConfiguration(document:fileURL:) and a .constant binding so the surface can be exercised in isolation.

Try it — Change the fileURL argument to nil and watch the header fall back to "Untitled" through the lastPathComponent ?? "Untitled" expression.

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.

FileDocumentConfiguration.swift
struct FileDocumentConfigurationDemo: View {
    struct TextFile: FileDocument {
        static var readableContentTypes: [UTType] { [.plainText] }
        var text: String
        init(text: String = "Hello") { self.text = text }
        init(configuration: ReadConfiguration) throws {
            let data = configuration.file.regularFileContents ?? Data()
            text = String(decoding: data, as: UTF8.self)
        }
        func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
            FileWrapper(regularFileWithContents: Data(text.utf8))
        }
    }

    @State private var config = FileDocumentConfiguration(document: .constant(TextFile(text: "Draft notes")), fileURL: URL(fileURLWithPath: "/Documents/notes.txt"))

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(config.fileURL?.lastPathComponent ?? "Untitled")
                .font(.headline)
            TextEditor(text: config.$document.text)
                .frame(height: 120)
                .border(.secondary)
            Text(config.isEditable ? "Editable" : "Read-only")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .padding()
    }
}
Live preview
Untitled Read-only
Untitled Read-only
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →