How to export files using fileExporter()
How to export files using fileExporter() 관련
Updated for Xcode 15
SwiftUI has a fileExporter()
modifier that lets us export files from our app to anywhere the user wants – any folder in iCloud, or on their local device.
Using it takes several steps, because you must first have created a document type that your app is able to work with. I’m going to presume you’ve already done that so we can focus on fileExporter()
, but if you haven’t already created a document type see the end of this article – I’ll provide an example there.
First, you need some state to track when you want the exporter UI to show or not. This is a simple Boolean, so you’d use something like this:
@State private var showingExporter = false
The next step is to add the fileExporter()
modifier somewhere to your view hierarchy, passing in the Boolean state you just created, the document you want to export, and content type the document has.
Helpfully, the document parameter is optional, so you don’t need to have this set at all times. However, in order for the exporter UI to appear the document must be set and your state Boolean must have be true – you need both.
When the export operation completes, the file exporter will run a callback function of your choosing, passing in a Result
object that either contains the URL where the file was saved or an error.
So, you would add this kind of modifier to your view hierarchy:
.fileExporter(isPresented: $showingExporter, document: yourDocument, contentType: .plainText) { result in
switch result {
case .success(let url):
print("Saved to \(url)")
case .failure(let error):
print(error.localizedDescription)
}
}
Note
I used .plainText
for my content type, but that should match one of the content types you’ve set on your document type.
That’s all it takes to export a file, but just in case you’re missing this I want to provide an example document type that can be used here.
First, you’ll need to add a new import so that you can declare which content types your document can be used as:
import UniformTypeIdentifiers
And now you need to create some sort of type that conforms to the FileDocument
protocol. This doesn’t take much, but you do need to tell SwiftUI how to load and save files, and also give it an initializer able to create new instances as needed.
Here’s an example, with comments to explain what it all does:
struct TextFile: FileDocument {
// tell the system we support only plain text
static var readableContentTypes = [UTType.plainText]
// by default our document is empty
var text = ""
// a simple initializer that creates new, empty documents
init(initialText: String = "") {
text = initialText
}
// this initializer loads data that has been saved previously
init(configuration: ReadConfiguration) throws {
if let data = configuration.file.regularFileContents {
text = String(decoding: data, as: UTF8.self)
}
}
// this will be called when the system wants to write our data to disk
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let data = Data(text.utf8)
return FileWrapper(regularFileWithContents: data)
}
}