How it works
FileDocumentWriteConfiguration carries the information SwiftUI hands you when it needs to serialize a FileDocument to disk. When the document-based scene saves a file — through the user choosing Save, an autosave, or an export — the framework calls your document's fileWrapper(configuration:) method and passes an instance of this structure describing the write. You reach for it whenever you implement that method: it tells you the content type SwiftUI resolved for the destination and, on an overwrite, gives you access to the file's existing contents so you can update in place rather than rebuild from scratch.
Receive it in fileWrapper(configuration:)
FileDocumentWriteConfiguration only appears as the argument to a FileDocument's write method. The protocol exposes it through the WriteConfiguration typealias, so the signature reads
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper. SwiftUI constructs the value and invokes this method on a background context each time it persists the document; your job is to return a FileWrapper built from the document's current state, hereFileWrapper(regularFileWithContents: Data(text.utf8)).Read contentType to match the destination
The configuration's contentType property reports the UTType SwiftUI chose for the file being written, drawn from the document's declared
writableContentTypes(which default toreadableContentTypes,[.plainText]in the demo). When a document can write more than one format, you branch on contentType to decide how to encode the bytes; the TextDoc example writes a single plain-text representation, so it can ignore the property and always emit UTF-8.Reuse existingFile when overwriting
On a save that replaces a file already on disk, the configuration's existingFile property holds the prior FileWrapper, letting you preserve untouched parts of a package or perform an incremental update instead of regenerating everything. It is nil for a fresh write. The plain-text document fully rewrites its contents from
doc.texteach time, so it builds a new wrapper and never consults existingFile — but a directory-backed document would copy forward unchanged children from it.Return the FileWrapper SwiftUI persists
Whatever the method returns becomes the bytes on disk, so the write configuration frames a transformation: take the in-memory document and produce a FileWrapper. The example serializes the model's
textintoData(text.utf8)and wraps it; the byte count shown in the view,Data(doc.text.utf8).count, mirrors exactly what this method would hand back to SwiftUI for the active content type.
init(text: "Hello, document!") to a longer string and watch the "Bytes to write" line, which previews the size of the Data the fileWrapper(configuration:) write would produce.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 FileDocumentWriteConfigurationDemo: View {
struct TextDoc: FileDocument {
static var readableContentTypes: [UTType] { [.plainText] }
var text: String
init(text: String = "") { 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 {
// configuration: FileDocumentWriteConfiguration
FileWrapper(regularFileWithContents: Data(text.utf8))
}
}
@State private var doc = TextDoc(text: "Hello, document!")
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("FileDocument").font(.headline)
Text("Content type: .plainText")
Text("Bytes to write: \(Data(doc.text.utf8).count)")
.foregroundStyle(.secondary)
Text(doc.text)
.padding(8)
.background(.quaternary, in: RoundedRectangle(cornerRadius: 6))
}
.padding()
}
}