SwiftUI 中 DocumentGroups 的 FileDocument 和 ReferenceFileDocument 有什么区别?

What is the difference between `FileDocument` and `ReferenceFileDocument` for `DocumentGroups` in SwiftUI?

我正在尝试在我的应用程序中设置 DocumentGroup,但目前还没有示例 ReferenceFileDocument 适用。我知道 FileDocument 是什么,但 ReferenceFileDocument 有何不同。

docs中它说的是:

Conformance to ReferenceFileDocument is expected to be thread-safe, and deserialization and serialization will be done on a background thread.

ReferenceFileDocument 是一种将在后台自动保存的文档类型。它通过 UndoManager 通知更改,因此为了使用它,您还必须使您的文档可撤销。

我在文档中看到的唯一提及是 here

Here 是一个工作示例。

名称中有一个提示:ReferenceFileDocument 是一个引用类型的文档(即 class)。 FileDocument 用于基于结构的文档。

这对文档的保存方式有影响,因为 SwiftUI 可以只复制引用类型并保存它,而不用担心你在保存过程中出现并修改它,因为它是值类型或值树类型。

对于 ReferenceFileDocument,似乎也没有明确的方法让 SwiftUI 知道何时保存,所以这取决于你告诉它。没有直接的“doc is dirty,save it now”方法,所以你通知 SwiftUI 你做了一些需要保存的事情是通过撤销管理器。

您还需要提供 snapshot 方法来 return 可以安全保存的文档副本。

final class QuizDocument: ReferenceFileDocument, ObservableObject {
    
    @Published var quiz: QuizTemplate

    init(quiz: QuizTemplate) {
        self.quiz = quiz
    }

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

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let quiz = try? JSONDecoder().decode(QuizTemplate.self, from: data)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }

        self.quiz = quiz
    }

    // Produce a snapshot suitable for saving. Copy any nested references so they don't
    // change while the save is in progress.
    func snapshot(contentType: UTType) throws -> QuizTemplate {
        return self.quiz
    }

    // Save the snapshot
    func fileWrapper(snapshot: QuizTemplate, configuration: WriteConfiguration) throws -> FileWrapper {
        let data = try JSONEncoder().encode(quiz)
        return .init(regularFileWithContents: data)
    }
}