I develop iOS app and use fileExporter for exporting data to different text formats (csv, json etc). I moved “export” button view and models to separate files (struct and class) and got trouble when fileExporter does not appear. Seams like TextFileDocument is empty and I cant figure out why. Nothing happened after click on button “CSV”.
Thanks in advance for your ideas.
import SwiftUI
import UniformTypeIdentifiers
struct ExportButtonView: View {
@ObservedObject private var vm: ExportButtonViewModel = ExportButtonViewModel()
@State private var showingExporter: Bool = false
@State private var showingChooseExportDataType: Bool = false
var body: some View {
Image(systemName: "square.and.arrow.up")
.onTapGesture {
showingChooseExportDataType.toggle()
}
.confirmationDialog("Choose data format to export", isPresented: $showingChooseExportDataType, titleVisibility: .visible) {
Button("CSV") {
vm.initExportingTypeAndDocument(exportDataType: .csv)
showingExporter.toggle()
}
// Put here buttons for other formats
.fileExporter(
isPresented: $showingExporter,
document: vm.exportingDocument,
contentType: .plainText,
defaultFilename: "data.(vm.exportDataType)"
) { result in
switch result {
case .success(let url):
print("Saved to (url)")
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
}
class ExportButtonViewModel: ObservableObject {
var exportDataType: TextFileDataExporterManager.ExportDataType = .csv
var exportingDocument: TextFileDocument?
func initExportingTypeAndDocument(exportDataType: TextFileDataExporterManager.ExportDataType){
self.exportDataType = exportDataType
self.exportingDocument = TextFileDocument(initialText: TextFileDataExporterManager(data: ["Test1", "Test2"], dataFormatType: exportDataType).getFormattedText())
}
}
struct HomeView: View {
var body: some View {
ExportButtonView()
}
}
protocol TextFileDataExporter {
var data: [String] { get }
func getFormattedText() -> String
}
class TextFileDataExporterManager: TextFileDataExporter {
var data: [String]
let dataFormatType: ExportDataType
enum ExportDataType: String {
case csv
}
init(data: [String], dataFormatType: ExportDataType) {
self.data = data
self.dataFormatType = dataFormatType
}
func getFormattedText() -> String {
switch dataFormatType {
case .csv:
return CsvExporter(data: data).getFormattedText()
}
}
}
class CsvExporter: TextFileDataExporter {
var data: [String]
init(data: [String]) {
self.data = data
}
func getFormattedText() -> String {
return "Here;will;be;some;csv;data"
}
}
struct TextFileDocument: 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)
}
}