SwiftUI中如何为ShareLink共享的FileDocument设置默认文件名?
问题
我正在使用ShareLink共享一个包含字符串的FileDocument,该FileDocument已遵循Transferable协议。
对应的FileDocument结构体:
struct TransferableDocument: FileDocument, Transferable { static var transferRepresentation: some TransferRepresentation { DataRepresentation(exportedContentType: .text) { log in log.convertToData() } } // tell the system to support only text static var readableContentTypes: [UTType] = [.text] // by default the document is empty var text = "" // this initializer creates a empty document 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 the data to disk func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { let data = Data(text.utf8) return FileWrapper(regularFileWithContents: data) } func convertToData() -> Data { return text.data(using: .ascii) ?? Data() } }
对应的ShareLink代码:
var doc: TransferableDocument { return TransferableDocument(initialText: "I'm a String") } ShareLink(item: doc ,preview: SharePreview("logfile")) { Text("Share") }
目前通过AirDrop共享时,文件名会被设置为SharePreview的标题(即示例中的“logfile”),但共享至邮件等应用时,文件名仅显示为“text”。请问是否有办法为共享的文件设置统一的默认文件名?
解决方案
要实现跨应用的统一默认文件名,核心是在Transferable的transferRepresentation中显式指定文件名,而非依赖仅对部分渠道生效的SharePreview标题。
方法1:给DataRepresentation添加建议文件名
直接在现有DataRepresentation后链式调用.suggestedFileName(_:)方法,指定统一文件名(建议带上扩展名,比如.txt):
static var transferRepresentation: some TransferRepresentation { DataRepresentation(exportedContentType: .text) { document in document.text.data(using: .utf8) ?? Data() } .suggestedFileName("logfile.txt") // 显式指定文件名 }
方法2:使用FileRepresentation(更贴合FileDocument特性)
如果结构体已实现FileDocument,可以改用FileRepresentation构建传输表示并指定文件名:
static var transferRepresentation: some TransferRepresentation { FileRepresentation(exportedContentType: .text) { document in let fileWrapper = try document.fileWrapper(configuration: .init()) return .init(fileWrapper: fileWrapper, filename: "logfile.txt") } }
进阶:支持动态文件名
若需根据文档内容动态设置文件名,可给TransferableDocument添加filename属性,再在传输表示中使用该属性:
struct TransferableDocument: FileDocument, Transferable { static var transferRepresentation: some TransferRepresentation { DataRepresentation(exportedContentType: .text) { document in document.text.data(using: .utf8) ?? Data() } .suggestedFileName(document.filename) } static var readableContentTypes: [UTType] = [.text] var text = "" var filename: String // 新增文件名属性 init(initialText: String = "", filename: String = "logfile.txt") { self.text = initialText self.filename = filename } // 其余初始化方法和fileWrapper方法保持不变... } // 使用时可指定自定义文件名 var doc: TransferableDocument { return TransferableDocument(initialText: "I'm a String", filename: "custom_log.txt") }
修改后,AirDrop、邮件及其他支持文件共享的应用都会使用你指定的统一文件名。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

