SwiftUI: .fileExporterを使う
iOSにApple標準の「ファイル」appというのがあります。Finderみたいなものでしょうか。
ファイルを開いたり移動したりができます。
自前のAppからファイルを保存する際に、保存先を指定するのに「macOSならNSSavePanel
のようなものを使いますが、iOSではUIDocumentPickerViewController
を使います」のような説明を見ることがあります。
で、これがiOS14以降、SwiftUIでは.fileExporter
という修飾子で同じ機能を使えるようになっているということだったので使ってみました。UIDocumentPickerViewController
や. fileExporter
で、「ファイル」appを起動するようなイメージになります。イメージピッカーもiOS14ぐらいだったかに別アプリになったのと同様、セキュリティ/プライバシー管理が強化された一環なんでしょうね。
で、結論から言うと「保存先の指定というのとはかなり違う。エクスポートあるいは保存、というよりは、すでに保存してあるファイルを移動するのに使用する」ということのようです。NSSavePanel
は保存先の指定のイメージですが、UIDocumentPickerViewController
や.fileExporter
は移動です。そもそも全然違うんですね。
「移動」のイメージであるがゆえに.fileExporter
を使うと以下のようになります。
-
.fileExporter(isPresented:document:contentType:completionHandler:)
のdocument:
は、ビューの構築時に評価される。なので、ここにファイルの生成処理を書いていると、エクスポート画面が表示されるタイミングではなく、呼び出し元のビュー構築時にファイルが生成される。ファイル生成自体が時間のかかる処理だと、呼び出し元ビューがなかなか表示されないということもあり得る。 - エクスポート画面のボタン名は「保存」ではなく「移動」(英語環境では「Save」ではなく「Move」)となる。これは変更できない。
1に関しては(これから試しますが)isPresented:
のフラグをONに変える直前のタイミングでファイルの中身を生成するようにしたらいいのかなと考えています。
2はもうどうしようもなさそうです。「保存」に見せかけたい、というデベロッパからの要望も多そうな気はするのですが…
1に関しては(これから試しますが)isPresented:のフラグをONに変える直前のタイミングでファイルの中身を生成するようにしたらいいのかなと考えています。
これで良さそうでした。
FileDocument
プロトコルのfileWrapper(configuration:)
の呼び出し時に、実際のファイルの中身を生成して返せば良いので、ビュー構築時の.fileExporter
のところではファイルの中身を生成しないようにします。