把数据流方向想清楚

SwiftUI 界面是状态的函数:状态一变,界面自动重画。进阶的第一课是弄清楚数据从哪来、往哪去。子视图不该自己造数据,而由父视图传下来;子视图要改数据,要么回调要么双向绑定。数据流方向单一,界面才不会互相乱改。

SwiftUI 的心智模型:声明界面长什么样,剩下的让框架在状态变化时替你更新。

这篇顺着数据流、动画、自定义布局三件事,把 SwiftUI 从入门带到进阶。

@State 到 @Observable

简单的值状态用 @State 包在视图里。稍复杂的模型对象,用 @Observable 标注整个类,视图里直接观测它的属性,属性一变用到它的视图就刷新。相比老的 ObservableObject 加 @Published,新写法少了样板。

@Observable
class Profile {
  var name: String = ""
  var age: Int = 0
}

视图里用 @State 持有一个 Profile 实例,或用 @Environment 从上层注入。

单向数据流与绑定

父传子用 let 属性;子要回写用 @Binding,它是一个双向连接:子视图改它,父视图的值跟着变。表单输入就是典型——TextField 绑定到父级状态,输入即时反映上去。

属性包装器速查
  • @State视图内部私有状态。
  • @Binding与外部双向连接。
  • @Observable可观测模型对象。
  • @Environment从环境注入共享值。

隐式与显式动画

SwiftUI 做动画出奇地简单:改一个状态值,包在 withAnimation 里,相关视图自动补间。这是显式动画;隐式动画则给某个视图加 .animation,它关心的值一变就自动动。

Button("展开") {
  withAnimation(.easeOut(duration: 0.3)) { expanded.toggle() }
}
.frame(height: expanded ? 200 : 80)

高度从 80 到 200 平滑过渡,不用手写逐帧。

过渡与转场

视图出现消失时,用 transition 决定怎么进场退场:opacity、offset、scale 可以自由组合。配合条件渲染,一个视图的插入和移除就有了优雅的动画,而不是突然蹦出来。

SwiftUI 进阶示意:发光数据流从左侧流入一个网格窗口,窗口内多张卡片随动效轨迹流动
数据流与布局:数据流入布局框架,卡片随动效排列。

NavigationStack 的推送也能加 hero 转场,让列表项平滑放大成详情。