SwiftUI导入导出PDF及Word文档功能异常问题咨询
问题根源
- 你当前的
MessageDocument是专为纯文本格式设计的,只能读写UTF8编码的字符串,PDF、doc属于二进制文件,直接将二进制数据转为UTF8字符串会失败,所以document一直保留初始的"Hello World"值,导出自然只有这段文本 - 原有
fileImporter逻辑错误将二进制文件内容强制转UTF8字符串,fileExporter也没有指定对应二进制文件的正确类型
修复步骤
1. 重构MessageDocument支持二进制文件
替换原有MessageDocument代码,改为存储二进制Data而非纯文本String:
import SwiftUI import UniformTypeIdentifiers struct GeneralDocument: FileDocument { // 支持的导入格式:可按需增删 static var readableContentTypes: [UTType] { [.pdf, .docx, UTType("com.microsoft.word.doc")!, .plainText] } // 存储文件二进制原始数据 var fileData: Data // 可选:存储文件类型,导出时用 var fileType: UTType? init(data: Data, type: UTType? = nil) { self.fileData = data self.fileType = type } init(configuration: ReadConfiguration) throws { guard let data = configuration.file.regularFileContents else { throw CocoaError(.fileReadCorruptFile) } self.fileData = data self.fileType = configuration.contentType } func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { return FileWrapper(regularFileWithContents: fileData) } }
2. 修改声明的document属性
// 替换原有MessageDocument声明 @State private var document: GeneralDocument = GeneralDocument(data: "Hello, World!".data(using: .utf8)!) // 可选:存储导入的文件名,导出时复用 @State private var importedFileName: String?
3. 修正fileImporter逻辑
删除二进制转UTF8字符串的错误逻辑,直接读取原始Data:
.fileImporter( isPresented: $isImporting, // 支持导入的格式和GeneralDocument里保持一致 allowedContentTypes: GeneralDocument.readableContentTypes, allowsMultipleSelection: false ) { result in do { guard let selectedFile: URL = try result.get().first else { return } if selectedFile.startAccessingSecurityScopedResource() { defer { selectedFile.stopAccessingSecurityScopedResource() } // 直接读取二进制原始数据 let fileData = try Data(contentsOf: selectedFile) // 获取文件类型 let fileType = UTType(filenameExtension: selectedFile.pathExtension) // 存储文件名 importedFileName = selectedFile.deletingPathExtension().lastPathComponent // 赋值给document document = GeneralDocument(data: fileData, type: fileType) } else { print("Permission error!") } } catch { print(error.localizedDescription) } }
4. 修正fileExporter配置
指定正确的导出类型和文件名:
.fileExporter( isPresented: $isExporting, document: document, // 导出用导入的文件类型,默认PDF可自行修改 contentType: document.fileType ?? .pdf, // 复用导入的文件名,默认名自行修改 defaultFilename: importedFileName ?? "导出文件" ) { result in switch result { case .success(let url): print("导出成功: \(url)") case .failure(let error): print("导出失败: \(error.localizedDescription)") } }
补充说明
- 如果仅需要支持PDF格式,可删除
readableContentTypes里的doc、docx相关类型 - 导入doc格式需要注意:系统原生UTType没有直接提供
.doc常量,需要用UTType("com.microsoft.word.doc")!手动声明 - 导出不同格式时可自行修改
contentType参数,对应导出正确的文件后缀
内容的提问来源于stack exchange,提问作者Mert Köksal
相关产品推荐
相关产品推荐

