SwiftUI Patterns 是一套面向 Apple 平台的现代 SwiftUI 开发模式指南,目标是帮助开发者构建声明式、高性能的用户界面。其内容覆盖 Observation 框架、视图组合、类型安全导航与性能优化。
适用时机 当你在构建 SwiftUI 视图并管理状态(@State、@Observable、@Binding)、使用 NavigationStack 设计导航流程、组织视图模型与数据流、优化列表与复杂布局的渲染性能,或在 SwiftUI 中处理环境值与依赖注入时,可以启用该技能。
状态管理 属性包装器的选择原则是:选用能满足需求的最简单包装器。@State 用于视图本地的值类型(开关、表单字段、sheet 呈现);@Binding 用于对父级 @State 的双向引用;@Observable 类配合 @State 用于拥有多个属性的自有模型;不带包装器的 @Observable 类用于从父级传入的只读引用;@Bindable 用于对 @Observable 属性的双向绑定;@Environment 用于通过 .environment() 注入的共享依赖。
视图模型应使用 @Observable 而非 ObservableObject,因为它能跟踪属性级变化,使 SwiftUI 只重新渲染读取了该变化属性的视图。示例中 ItemListViewModel 通过 @Observable 标注,持有 items、isLoading、searchText 等状态,并注入 ItemRepository 依赖,在 load() 方法中异步获取数据。视图侧用 @State 持有 viewModel,通过 List 渲染、.searchable 绑定搜索文本、.overlay 显示加载指示、.task 触发加载。
环境注入方面,用 @Environment 替代 @EnvironmentObject:注入时调用 .environment(authManager),消费时声明 @Environment(AuthManager.self) private var auth。
视图组合 将视图拆分为小而专注的结构体,可限制失效范围:状态变化时只有读取该状态的子视图会重新渲染。示例 OrderView 将标题、列表、合计拆为 OrderHeader、OrderItemList、OrderTotal 三个子视图。可复用样式通过 ViewModifier 实现,例如 CardModifier 添加内边距、材质背景与圆角裁剪,再通过 View 扩展方法 cardStyle() 调用。
导航 使用 NavigationStack 配合 NavigationPath 实现可编程、类型安全的导航。示例中 Router 类用 @Observable 标注,持有 path,提供 navigate(to:) 与 popToRoot() 方法;Destination 枚举遵循 Hashable,包含 detail、settings、profile 等分支。RootView 用 @State 持有 router,在 NavigationStack(path:) 中通过 navigationDestination(for:) 按目标类型分发到对应视图,并通过 .environment(router) 注入。
性能优化 对大集合使用 LazyVStack 与 LazyHStack,仅在可见时创建视图。ForEach 中始终使用稳定唯一的 ID,避免使用数组下标,可通过 Identifiable 遵循或显式 id 指定。不要在 body 中执行 I/O、网络调用或重计算;异步工作使用 .task {},它会在视图消失时自动取消。在滚动视图中谨慎使用 .sensoryFeedback() 与 .geometryGroup();在列表中尽量减少 .shadow()、.blur()、.mask(),因为它们会触发离屏渲染。对于 body 开销大的视图,可遵循 Equatable 以跳过不必要的重新渲染,示例 ExpensiveChartView 通过比较 dataPoints 判断是否相等。
预览 使用 #Preview 宏配合内联模拟数据加速迭代,例如分别预览空状态与已加载状态,通过传入不同的模拟仓库实现。
应避免的反模式 在新代码中使用 ObservableObject / @Published / @StateObject / @EnvironmentObject,应迁移到 @Observable;把异步工作直接放在 body 或 init 中,应改用 .task {} 或显式加载方法;在并不拥有数据的子视图中把视图模型创建为 @State,应从父级传入;使用 AnyView 类型擦除,应优先使用 @ViewBuilder 或 Group 处理条件视图;在向 actor 传递数据或从 actor 返回数据时忽略 Sendable 要求。
相关参考 该技能提及可参见 swift-actor-persistence(基于 actor 的持久化模式)与 swift-protocol-di-testing(基于协议的依赖注入与使用 Swift Testing 的测试)。