在 SwiftUI 中,DocumentGroup
和 WindowGroup
是两种不同的视图容器,用于管理应用的多个窗口/场景。它们的用途和功能有所不同,但都与多窗口或多场景支持密切相关。
具体来说:
DocumentGroup
是专为文档型(document-based)的应用设计的窗口管理容器。WindowGroup
是一个通用的窗口场景容器,适用于任何应用场景,不限制特定类型的内容。
它们的核心区别在于用途、适用场景以及背后的功能特性。
1. 什么是 DocumentGroup
?
#
DocumentGroup
是 SwiftUI 中专门为 文档型应用(Document-based Apps) 提供的窗口/场景容器。 它帮助开发者处理文件的创建、打开、保存等功能。这种窗口的主要特征是它基于文档模型,每一个窗口都和一个文档(文件)绑定。
适用场景: #
DocumentGroup
广泛用于需要支持多文档操作的应用,例如:
- 文字处理器(如 Pages, Microsoft Word)。
- 代码编辑器(如 Xcode, TextEdit)。
- 图形编辑应用(如 Sketch, Photoshop)。
- 表格处理工具(如 Numbers, Excel)。
DocumentGroup
的特点是,用户可以通过系统提供的文件管理功能选择打开一个文件,同时每个文档会实例化一个独立的窗口(或场景)。
如何使用 DocumentGroup
?
#
- 支持文档:为了使用
DocumentGroup
,你需要有一个FileDocument
类型的数据模型。FileDocument
是 SwiftUI 提供的协议,必须实现数据的加载、保存等行为。
示例代码: #
下面是一个简单的文档型应用(iOS/macOS)的实现例子:
文档数据模型实现:
import SwiftUI
import UniformTypeIdentifiers
// 定义文档数据模型(存储为文本文件)
struct MyTextDocument: FileDocument {
// 数据内容
var text: String = ""
// 定义支持的文件类型
static var readableContentTypes: [UTType] { [.plainText] }
// 初始化方法:从文件加载(收到数据后解码)
init(configuration: ReadConfiguration) throws {
if let data = configuration.file.regularFileContents,
let string = String(data: data, encoding: .utf8) {
text = string
} else {
throw CocoaError(.fileReadCorruptFile) // 解析错误抛出异常
}
}
// 保存数据到文件时的行为
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let data = text.data(using: .utf8)! // 转换为 UTF-8 数据
return FileWrapper(regularFileWithContents: data)
}
// 默认初始化(新文档)
init() {}
}
DocumentGroup
主应用入口:
@main
struct MyDocumentApp: App {
var body: some Scene {
// 定义为 DocumentGroup
DocumentGroup(newDocument: MyTextDocument()) { file in
// 提供一个绑定的视图,显示文件内容
TextEditor(text: file.$document.text)
.padding()
}
}
}
代码解析: #
- 文件模型(
MyTextDocument
):
- 实现了
FileDocument
协议。 - 定义了文件的存储和加载逻辑,支持文本文件(
.txt
)。
DocumentGroup
场景:
DocumentGroup
是应用的主入口,它会自动处理文档的打开、创建等所有文件相关操作。- 每个文档会与一个绑定的视图实例化一个独立的窗口/场景。
- 使用
file.$document
提供双向绑定,直接操作文件内容。
运行效果: #
- 应用打开后,可以选择创建新文档或打开已有文档。
- 每次打开一个新文档都会创建新窗口,并针对文件内容自动加载、显示或保存。
DocumentGroup
的优势
#
- 系统级文件集成功能:
包括文件打开选择器(Open/Save Panel),自动管理文件的加载和保存。 - 多文档支持:
每个文档都可以独立管理、绑定到一个窗口。 - 操作简化:
DocumentGroup
自动帮助管理文档加载、保存等核心工作,开发者重点关注界面和逻辑实现即可。
局限性: #
DocumentGroup
强依赖于文档模型(FileDocument
),如果你的应用不涉及文件或文档操作,它就显得不适合。
2. 什么是 WindowGroup
?
#
WindowGroup
是 SwiftUI 提供的通用场景容器,适用于大部分应用类型。它不依赖于文件或文档模型,可以用于管理应用中的主窗口和多窗口的应用场景。
WindowGroup
的适用场景:
#
非文档型应用:
例如社交媒体(如 Twitter)、工具型应用(如 Notes)、游戏等。
不适合用
DocumentGroup
的应用功能,通常会用WindowGroup
来实现主界面。多窗口支持:
WindowGroup
可以让用户在支持多窗口的平台(macOS、iPadOS)上自由打开多个独立的窗口。主/场景容器:
对于单窗口的 iPhone 应用,
WindowGroup
是最常用的入口场景包装器。
如何使用 WindowGroup
?
#
示例 1:单窗口应用 #
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView() // 应用的主界面
}
}
}
示例 2:多窗口支持 #
如果想让用户在 macOS 或 iPadOS 上打开多个独立的窗口,可以在 WindowGroup
中提供动态数据支持。
struct Note: Identifiable {
var id = UUID()
var title: String
}
@main
struct MyApp: App {
@State private var notes: [Note] = [Note(title: "Note 1"), Note(title: "Note 2")]
var body: some Scene {
WindowGroup {
List(notes) { note in
Text(note.title)
}
}
}
}
在多窗口平台上,每次用户新建一个窗口都会加载一个新的 WindowGroup
实例。
3. 两者的区别 #
特性 | DocumentGroup | WindowGroup |
用途 | 专为文档管理设计,为每个窗口关联一个文件 | 通用功能的场景容器,用于任何非文档型应用 |
依赖模型 | 必须基于 FileDocument 模型,实现加载/保存行为 | 不依赖特定数据模型,可以用于任意场景 |
文件管理能力 | 内置文件的加载、保存、创建、打开界面 | 无原生文件管理功能 |
系统集成 | 自动与系统的文件处理机制集成(如 macOS 的 Finder) | 无特定集成,需手动添加文件管理功能 |
多窗口支持 | 每个窗口对应一个文档 | 支持动态生成多个不受约束的窗口 |
适用场景 | 文档型应用(文字、图形、表格编辑等) | 非文档型应用(工具、社交、游戏等) |
总结 #
DocumentGroup
:专注于文档操作,通过FileDocument
管理文件加载、保存。适合创建多文档型应用,提供系统文件管理集成的优越体验。WindowGroup
:更通用,适合大部分非文档应用(如工具、游戏等)。提供多窗口、跨场景支持,但不具备与系统文件管理的深度整合。
如果你的应用涉及文档处理,优先选择 DocumentGroup
;否则,应使用更灵活的 WindowGroup
。