将视图模型绑定到视图
使用 SwiftUI 和 Combine 连接视图模型。
将视图模型绑定到视图 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
将视图模型连接到视图
只有当视图响应视图模型的变化时,视图模型才有用。在 SwiftUI 中,这种响应式能力由基于 Combine 的属性包装器 @Published、@StateObject 和 @ObservedObject 提供。
它们共同形成自动绑定:视图模型发生变化时,视图会重新渲染。
ObservableObject
要让 SwiftUI 观察视图模型,视图模型必须遵循 ObservableObject。该协议为它提供了一个 objectWillChange 发布者,该发布者会在任何变化发生前触发。
final class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}@Published 属性
使用 @Published 标记属性后,每当该属性被设置新值时,系统都会自动发出变化通知。
每个 @Published 属性都会向对象的 objectWillChange 发布者提供变化,因此视图能够准确知道何时刷新。
final class SearchViewModel: ObservableObject {
@Published var query: String = ""
@Published var results: [String] = []
}@StateObject
@StateObject 告诉视图创建并拥有一个视图模型。SwiftUI 会实例化它一次,并在该视图重新渲染期间保持它存活。
在首次创建视图模型的地方使用 @StateObject。
struct CounterView: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
Button("Count: \(viewModel.count)") {
viewModel.increment()
}
}
}@ObservedObject
@ObservedObject用于已经在其他地方创建并传入的视图模型。视图会观察它,但不负责管理它的生命周期。
对于从父级接收视图模型的子级视图,请使用它。
struct BadgeView: View {
@ObservedObject var viewModel: CounterViewModel
var body: some View {
Text("Total: \(viewModel.count)")
}
}StateObject 与 ObservedObject
关键区别在于所有权:
- @StateObject — 由视图拥有;在重新渲染后仍然保留
- @ObservedObject — 从外部传入;不由视图拥有
应该使用 @StateObject 却使用了 @ObservedObject,可能会导致对象在每次父级更新时重新创建并丢失状态。
向下传递视图模型
在父级中使用 @StateObject 创建一次视图模型,然后将它传递给使用 @ObservedObject 标记的子级。
struct ParentView: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
VStack {
BadgeView(viewModel: viewModel)
Button("Add") { viewModel.increment() }
}
}
}双向绑定
对于文本字段等输入控件,您需要双向绑定。SwiftUI 使用包装器上的 $ 前缀,根据 @Published 属性生成绑定。
struct SearchView: View {
@StateObject private var viewModel = SearchViewModel()
var body: some View {
TextField("Search", text: $viewModel.query)
}
}驱动用户界面状态
视图应该从已发布的属性中派生出所有要显示的内容。加载指示器、错误横幅和内容都由视图模型状态驱动。
final class FeedViewModel: ObservableObject {
enum State { case loading, loaded([String]), error(String) }
@Published var state: State = .loading
}响应状态
视图根据视图模型状态进行切换,以渲染正确的用户界面。这里没有命令式的显示或隐藏代码,只有声明式映射。
struct FeedView: View {
@StateObject var viewModel = FeedViewModel()
var body: some View {
switch viewModel.state {
case .loading: ProgressView()
case .loaded(let items): List(items, id: \.self) { Text($0) }
case .error(let message): Text(message)
}
}
}在主线程上保持更新
SwiftUI 要求在主线程上发布变化。当视图模型在异步工作完成后更新状态时,请使用 @MainActor 标注它,以确保这一点。
@MainActor
final class ProfileViewModel: ObservableObject {
@Published var name: String = ""
func load() async {
name = await fetchName()
}
}快速检查
测试您对绑定的理解。
回顾
您已经使用 SwiftUI 绑定将视图模型连接到视图:
- ObservableObject 与 @Published 会发出变化通知
- @StateObject 创建并拥有视图模型
- @ObservedObject 观察一个传入的视图模型
- @MainActor 让异步更新保持在主线程上
建立响应式绑定后,视图始终会自动反映视图模型的最新状态。
常见问题解答
「将视图模型绑定到视图」课时是免费的吗?
是的 — 「将视图模型绑定到视图」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「将视图模型绑定到视图」这节课中我会学到什么?
使用 SwiftUI 和 Combine 连接视图模型。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「将视图模型绑定到视图」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。