介绍
# SwiftUI UI Patterns
## 快速开始
根据你的目标选择一个路径:
### 现有项目
- 确定功能或屏幕及其主要交互模型(列表、详情、编辑器、设置、标签页)。 - 在仓库中用 `rg "TabView\("` 或类似命令查找附近的示例,然后阅读最近的 SwiftUI 视图。 - 应用本地惯例:优先使用 SwiftUI 原生状态,尽可能保持状态局部化,并使用环境注入来处理共享依赖。 - 从 `references/components-index.md` 选择相关的组件参考,并遵循其指导。 - 使用小型、专注的子视图和 SwiftUI 原生数据流来构建视图。
### 新项目脚手架
- 从 `references/app-scaffolding-wiring.md` 开始,搭建 TabView + NavigationStack + sheets。 - 基于提供的骨架添加一个最小的 `AppTab` 和 `RouterPath`。 - 根据你首先需要的 UI(TabView、NavigationStack、Sheets)选择下一个组件参考。 - 随着新屏幕的添加,扩展路由和 sheet 枚举。
## 需遵循的通用规则
- 使用现代 SwiftUI 状态(`@State`、`@Binding`、`@Observable`、`@Environment`),避免不必要的视图模型。 - 优先使用组合;保持视图小而专注。 - 将 async/await 与 `.task` 以及显式的加载/错误状态一起使用。 - 仅在编辑遗留文件时保留现有的遗留模式。 - 遵循项目的格式化程序和风格指南。 - **Sheets**:当状态代表所选模型时,优先使用 `.sheet(item:)` 而不是 `.sheet(isPresented:)`。避免在 sheet 主体中使用 `if let`。Sheets 应该拥有自己的操作,并在内部调用 `dismiss()`,而不是转发 `onCancel`/`onConfirm` 闭包。
## 新 SwiftUI 视图的工作流
1. 定义视图的状态及其所有权位置。 2. 识别要通过 `@Environment` 注入的依赖项。 3. 草拟视图层次结构并将重复部分提取为子视图。 4. 使用 `.task` 实现异步加载,并在需要时使用显式的状态枚举。 5. 当 UI 具有交互性时,添加无障碍标签或标识符。 6. 通过构建进行验证,并在需要时更新调用点的用法。
## 组件参考
使用 `references/components-index.md` 作为入口点。每个组件参考应包括: - 意图和最佳适用场景。 - 遵循本地惯例的最小使用模式。 - 陷阱和性能注意事项。 - 当前仓库中现有示例的路径。
## Sheet 模式
### 由 Item 驱动的 Sheet(首选)
```swift @State private var selectedItem: Item?
.sheet(item: $selectedItem) { item in EditItemSheet(item: item) } ```
### Sheet 拥有其操作
```swift struct EditItemSheet: View { @Environment(\.dismiss) private var dismiss @Environment(Store.self) private var store
let item: Item @State private var isSaving = false
var body: some View { VStack { Button(isSaving ? "Saving…" : "Save") { Task { await save() } } } }
private func save() async { isSaving = true await store.save(item) dismiss() } } ```
## 添加新的组件参考
- 创建 `references/<component>.md`。 - 保持简短且可执行;链接到当前仓库中的具体文件。 - 在 `references/components-index.md` 中用新条目进行更新。