swiftui-ui-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSwiftUI UI Patterns
SwiftUI 界面模式
Quick start
快速开始
Choose a track based on your goal:
根据你的目标选择路径:
Existing project
现有项目
- Identify the feature or screen and the primary interaction model (list, detail, editor, settings, tabbed).
- Find a nearby example in the repo with or similar, then read the closest SwiftUI view.
rg "TabView\(" - Apply local conventions: prefer SwiftUI-native state, keep state local when possible, and use environment injection for shared dependencies.
- Choose the relevant component reference from and follow its guidance.
references/components-index.md - Build the view with small, focused subviews and SwiftUI-native data flow.
- 确定功能或屏幕以及主要交互模型(列表、详情、编辑器、设置、标签页)。
- 使用或类似命令在仓库中找到相近的示例,然后阅读最接近的SwiftUI视图。
rg "TabView\(" - 遵循本地约定:优先使用SwiftUI原生状态,尽可能保持状态本地化,通过环境注入共享依赖。
- 从中选择相关组件参考并遵循其指南。
references/components-index.md - 使用小型、专注的子视图和SwiftUI原生数据流构建视图。
New project scaffolding
新项目脚手架
- Start with to wire TabView + NavigationStack + sheets.
references/app-scaffolding-wiring.md - Add a minimal and
AppTabbased on the provided skeletons.RouterPath - Choose the next component reference based on the UI you need first (TabView, NavigationStack, Sheets).
- Expand the route and sheet enums as new screens are added.
- 从开始,配置TabView + NavigationStack + 弹窗(sheets)。
references/app-scaffolding-wiring.md - 基于提供的骨架添加最小化的和
AppTab。RouterPath - 根据你首先需要的UI选择下一个组件参考(TabView、NavigationStack、Sheets)。
- 添加新屏幕时扩展路由和弹窗枚举。
General rules to follow
需遵循的通用规则
- Use modern SwiftUI state (,
@State,@Binding,@Observable) and avoid unnecessary view models.@Environment - Prefer composition; keep views small and focused.
- Use async/await with and explicit loading/error states.
.task - Maintain existing legacy patterns only when editing legacy files.
- Follow the project's formatter and style guide.
- Sheets: Prefer over
.sheet(item:)when state represents a selected model. Avoid.sheet(isPresented:)inside a sheet body. Sheets should own their actions and callif letinternally instead of forwardingdismiss()/onCancelclosures.onConfirm
- 使用现代SwiftUI状态(、
@State、@Binding、@Observable),避免不必要的视图模型。@Environment - 优先采用组合方式;保持视图小巧且专注。
- 将async/await与结合使用,并显式处理加载/错误状态。
.task - 仅在编辑遗留文件时遵循现有遗留模式。
- 遵循项目的格式化和样式指南。
- 弹窗(Sheets):当状态代表选中的模型时,优先使用而非
.sheet(item:)。避免在弹窗内容中使用.sheet(isPresented:)。弹窗应自行管理其操作,并在内部调用if let,而不是传递dismiss()/onCancel闭包。onConfirm
Workflow for a new SwiftUI view
新SwiftUI视图的工作流程
- Define the view's state and its ownership location.
- Identify dependencies to inject via .
@Environment - Sketch the view hierarchy and extract repeated parts into subviews.
- Implement async loading with and explicit state enum if needed.
.task - Add accessibility labels or identifiers when the UI is interactive.
- Validate with a build and update usage callsites if needed.
- 定义视图的状态及其所属位置。
- 确定要通过注入的依赖项。
@Environment - 勾勒视图层次结构,并将重复部分提取为子视图。
- 若需要,使用实现异步加载并显式定义状态枚举。
.task - 当UI具有交互性时,添加无障碍标签或标识符。
- 构建并验证,必要时更新调用位置。
Component references
组件参考
Use as the entry point. Each component reference should include:
references/components-index.md- Intent and best-fit scenarios.
- Minimal usage pattern with local conventions.
- Pitfalls and performance notes.
- Paths to existing examples in the current repo.
将作为入口点。每个组件参考应包含:
references/components-index.md- 用途和最适用场景。
- 符合本地约定的最小使用模式。
- 注意事项和性能说明。
- 当前仓库中现有示例的路径。
Sheet patterns
弹窗模式
Item-driven sheet (preferred)
基于项目的弹窗(推荐)
swift
@State private var selectedItem: Item?
.sheet(item: $selectedItem) { item in
EditItemSheet(item: item)
}swift
@State private var selectedItem: Item?
.sheet(item: $selectedItem) { item in
EditItemSheet(item: item)
}Sheet owns its actions
弹窗自行管理操作
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()
}
}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()
}
}Adding a new component reference
添加新组件参考
- Create .
references/<component>.md - Keep it short and actionable; link to concrete files in the current repo.
- Update with the new entry.
references/components-index.md
- 创建文件。
references/<component>.md - 保持内容简洁且可操作;链接到当前仓库中的具体文件。
- 在中添加新条目。
references/components-index.md