在 SwiftUI 文档应用程序中,如何从函数内保存文档

7 macos document-based swift swiftui

当前版本的 Xcode(版本 12.5.1)为 macOS 的基于文档的应用程序提供了一个模板,提供以下文档模型:

struct MyDocument: FileDocument {
    var text: String

    init(text: String = "Hello, world!") {
        self.text = text
    }

    static var readableContentTypes: [UTType] { [.exampleText] }

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let string = String(data: data, encoding: .utf8)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        text = string
    }
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        let data = text.data(using: .utf8)!
        return .init(regularFileWithContents: data)
    }
}
Run Code Online (Sandbox Code Playgroud)

我想向此结构添加一个方法,将我的文档传递给外部程序,同时在执行此操作之前保存文档:

func passMyDocumentToProgram() {
    // Save document
    // Pass document to external program
}
Run Code Online (Sandbox Code Playgroud)

问题是我不知道如何保存这样的文档。

生成的应用程序(从模板构建)提供了保存文档的功能(在菜单栏中),因此我应该以某种方式调用此现有功能。

根据我的理解,fileWrapper中的方法MyDocument返回一个FileWrapper具有write()可用于保存文档的方法;但是,该fileWrapper方法需要一个WriteConfiguration,我不知道如何创建它。相关文档WriteConfiguration非常稀疏,我在网上找不到任何有效的内容。

更新。更好的问题是如何触发我的文档应用程序自动保存?

我发现我可以用类似的东西保存我的文档FileWrapper(regularFileWithContents: data).write( ... ),但这是一个坏主意,因为你的应用程序会给你一个错误,说外部程序修改了文件。

使用该协议编写的 SwiftUI 文档应用程序会FileDocument在某些事件上自动保存文档,例如(取消)聚焦窗口,因此我想知道是否有一种方法可以以编程方式触发此类自动保存。

小智 3

按照与/sf/answers/4783225821/类似的过程,我们可以尝试获取Save...菜单项使用的实现。看着

\n
let menu = NSApp.mainMenu!.items.first(where: { $0.title == "File" })!\nlet submenu = menu.submenu!.items.first(where: { $0.title == "Save\xe2\x80\xa6" })!\nsubmenu.target // nil\nsubmenu.action // saveDocument:\n
Run Code Online (Sandbox Code Playgroud)\n

我想出了以下方法MyDocument

\n
func save() {\n    NSApp.sendAction(#selector(NSDocument.save(_:)), to: nil, from: nil)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

注释saveDocument已重命名为save. 根据我的理解,这尝试将save()选择器发送到关键窗口中可以对其做出反应的第一个对象。就我而言,关键窗口将包含用户正在编辑的文档,因此这将保存文档。

\n