SwiftUIでユーザーにファイルを保存させたいときに便利なのが .fileExporter() です。
ドキュメントファイルやユーザーによるデータ出力が必要な場面で、システム標準のファイル保存UIを簡潔に導入できます。
この記事では .fileExporter() の基本的な意味や使い方、主要な引数の意味、活用シーン、注意点までをわかりやすく丁寧に解説します。
.fileExporter() とは?
.fileExporter() は SwiftUIにおけるモディファイアの一種で、ユーザーにファイルを保存するためのダイアログUIを提供します。
つまり、「保存先を選ぶUI」と「その場所にデータを書き込む処理」をセットで簡単に呼び出せる仕組みです。
UIKitであれば UIDocumentPickerViewController を自分で呼び出して処理をつなげる必要がありましたが、SwiftUIでは .fileExporter() を書くだけで同じことがより直感的に実現できます。
具体例:テキストファイルを書き出す
このサンプルコードは、アプリ内で入力したテキストを実際のファイルとして保存する流れを示しています。
ボタンを押すとファイル保存のダイアログが表示され、入力したテキストを .txt ファイルに書き出せるようになります。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import SwiftUI import UniformTypeIdentifiers struct ContentView: View {     @State private var isExporterPresented = false     @State private var textToSave = "保存するテキスト"     @State private var didSave = false     var body: some View {         VStack {             TextEditor(text: $textToSave)                 .frame(height: 200)                 .border(.gray)             Button("テキストをファイルで保存") {                 isExporterPresented = true             }             if didSave {                 Text("保存しました")                     .foregroundColor(.green)             }         }         .fileExporter(             isPresented: $isExporterPresented,             document: TextDocument(text: textToSave),             contentType: .plainText,             defaultFilename: "Untitled"         ) { result in             switch result {             case .success:                 didSave = true             case .failure(let error):                 print("保存エラー: \(error.localizedDescription)")             }         }     } } struct TextDocument: FileDocument {     var text: String     static var readableContentTypes: [UTType] { [.plainText] }     init(text: String) {         self.text = text     }     init(configuration: ReadConfiguration) throws {         if let data = configuration.file.regularFileContents,            let string = String(data: data, encoding: .utf8) {             text = string         } else {             text = ""         }     }     func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {         let data = Data(text.utf8)         return .init(regularFileWithContents: data)     } } | 
この例では、TextEditorで編集した内容を TextDocument を通じてファイル保存しています。
保存が成功すれば画面に「保存しました」と表示され、失敗すればエラーメッセージがコンソールに出力されます。
つまり、ユーザーが書いたテキストをそのままアプリ外に出力できる仕組みを作っているわけです。
SwiftUIの標準UIと FileDocument を組み合わせることで、複雑な処理をほとんど書かずにファイル保存機能を実装できるのがポイントです。
主要な引数とその意味
.fileExporter() を正しく使うには、渡す引数の役割を理解しておくことが重要です。
ここで紹介する引数を押さえておくと、保存処理の仕組みやUIの挙動をコントロールしやすくなります。
それぞれの引数は次のような意味があります。
| 引数名 | 型 | 説明 | 
|---|---|---|
| isPresented | Binding | 保存UIを表示するトリガー | 
| document | FileDocument | 保存対象のデータモデル(FileDocument準拠) | 
| contentType | UTType | ファイルの種類(例: .plainText、.pdfなど) | 
| defaultFilename | String? | 保存ダイアログに表示するファイル名のデフォルト値 | 
| onCompletion | Result<Bool, Error> クロージャ | 保存成功/失敗を受け取る処理 | 
documentはFileDocumentプロトコルに準拠した構造体(例:TextDocument)で、読み書きロジックを明確に分離できます。
これらの引数を理解することで、ユーザーが保存UIを開いたときにどのようにファイルが作成され、保存後にどの処理が走るのかを正しく設計できるようになります。
指定の仕方
上記の引数を組み合わせて指定します。
これらを設定することで、どのタイミングで保存UIを出すか、どんな種類のファイルとして保存するか、保存後に何を行うかを決められます。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | .fileExporter(     isPresented: $isExporterPresented,         // 保存ダイアログを出すかどうか     document: TextDocument(text: textToSave),  // 保存する内容(FileDocument準拠)     contentType: .plainText,                   // ファイルの種類(ここでは .txt)     defaultFilename: "Untitled"                // デフォルトのファイル名 ) { result in     switch result {     case .success:         didSave = true                         // 成功時の処理     case .failure(let error):         print("保存エラー: \(error.localizedDescription)") // 失敗時の処理     } } | 
ここで特に大切なのは document と contentType の指定です。
document は FileDocument プロトコルに準拠した構造体(上記だとTextDocument構造体)を渡し、実際の保存処理の中身を定義します。
contentType は保存するファイルの種類を指定し、例えば .plainText や .pdf、.json などが使えます(今回だと.plainTextを指定しているので、.txt のテキストファイルが対象)
これらを正しく組み合わせることで、アプリに自然な形でファイル保存機能を組み込めます。
.fileExporter の活用シーン
.fileExporter() はアプリの中で「ユーザーがデータをエクスポートしたい」といったニーズに応えるために使われます。
単なるファイル保存に限らず、バックアップやレポート出力など幅広い場面で役立ちます。
.fileExporter() は以下のような場面で活用されます。
- ユーザーが編集したテキストやノートをファイルとして保存したいとき
- 画像やPDFなどをアプリからファイルとして書き出したい場合
- データのバックアップやエクスポートを実装したい機能
- SwiftUIアプリでのレポート出力機能(CSVやPDF)の導入
- ドキュメントアプリや編集アプリでのファイル共有フローに活用
シンプルな構成で、ファイルの書き出しUIを自然に追加できる点が魅力です。
特に、アプリ内だけに閉じられたデータではなく「外部で再利用できる形式」でユーザーがデータを扱えるようになる点が大きなメリットです。
.fileExporter を使うときの注意点
便利な .fileExporter() ですが、使う際にはいくつかの前提条件や注意すべきポイントがあります。
これらを理解しておくことで、予期しないエラーや動作不良を防ぐことができます。
- FileDocumentプロトコルの実装が必要で、読み書きロジックを定義する必要がある
- i- mport UniformTypeIdentifiersが必要(- contentTypeの指定にUTTypeを利用)
- iOS 14 / macOS 11 以降が対応対象(旧OSでは動作しない)
- 保存完了後に別処理を行いたい場合は、onCompletion内でResult<Bool, Error>を適切に処理すること
つまり、.fileExporter() を単体で使うだけではなく、必ず FileDocument と組み合わせて設計すること。
そして、OSバージョンやエラーハンドリングも考慮することが実践的な利用には欠かせません。
まとめ
今回は SwiftUI の .fileExporter() について詳しく紹介しました。
- .fileExporter()はユーザーにファイル保存UIを提供するモディファイア
- isPresentedや- document(FileDocument)、- contentType、- defaultFilenameの指定で挙動を制御
- ファイル書き出しが必要な多くの場面で活用できる汎用性の高い機能
- 保存成功・失敗の処理を onCompletionでハンドリング可能
SwiftUIでファイル書き出し機能を実装する際には、.fileExporter() を使うことでシンプルかつ宣言的に実装できます。
ぜひアプリの機能に組み込んでみてくださいね!