在 SwiftUI 中,@State
、@Bindable
和 @Binding
都用于管理和传递状态,但它们适用于不同的使用场景。
1. @State(本地状态)
@State
用于管理 视图本地的可变状态,该状态只属于当前视图,并且由 SwiftUI 负责存储和更新。
特点:
-
只能用于 结构体(struct)视图,因为 SwiftUI 视图是值类型。
-
适用于 视图内部的小型状态,如按钮点击状态、输入框文本等。
-
只能在 当前视图 中使用,不能直接传递给子视图。
示例:
struct CounterView: View {
@State private var count = 0 // 本地状态
var body: some View {
VStack {
Text("计数: \(count)")
Button("增加") {
count += 1 // 修改 @State 变量,SwiftUI 重新渲染视图
}
}
}
}
2. @Binding(状态绑定)
@Binding 用于 子视图获取父视图的状态,它本身不存储数据,而是引用 外部的状态(通常是 @State)。
特点:
-
@Binding 不拥有数据,而是对外部数据的引用。
-
用于 子视图修改父视图的状态,避免数据复制。
-
适用于 控制组件、表单、滑块等需要修改外部状态的视图。
示例:
struct ParentView: View {
@State private var isOn = false // 本地状态
var body: some View {
ToggleView(isOn: $isOn) // 传递 @Binding
}
}
struct ToggleView: View {
@Binding var isOn: Bool // 绑定外部的状态
var body: some View {
Toggle("开关状态", isOn: $isOn) // 直接修改外部状态
}
}
@Binding 前面要加 $ 取 绑定值,在子视图内部可直接读写该值。
3. @Bindable(可绑定的对象)【iOS 17+】
@Bindable 用于绑定 Observable 对象(通常是 ObservableObject),让 SwiftUI 视图可以自动响应对象属性的变化。
特点:
-
作用类似 @Binding,但适用于 类对象(Observable)。
-
依赖 Observable 协议(iOS 17 引入)。
-
适用于 需要双向绑定的复杂数据对象。
示例(结合 Observable)
import SwiftUI
@Observable class UserSettings {
var username: String = "张三"
}
struct ContentView: View {
@State private var settings = UserSettings() // `@State` 管理对象
var body: some View {
EditView(settings: $settings) // 传递 `@Bindable`
}
}
struct EditView: View {
@Bindable var settings: UserSettings // 绑定 Observable 对象
var body: some View {
TextField("用户名", text: $settings.username) // 绑定属性
}
}
这里 @Bindable var settings: UserSettings 允许 EditView 直接修改 settings.username,并且 SwiftUI 会自动更新 ContentView。
对比总结
属性修饰符 | 数据存储 | 作用范围 | 适用场景 |
---|---|---|---|
@State | 视图内部 | 仅当前视图 | 视图局部状态 |
@Binding | 外部状态(引用) | 子视图 | 子视图修改父视图状态 |
@Bindable | Observable 对象 | 子视图 | 绑定 Observable 类属性,适用于复杂数据 |
使用建议:
-
简单数据(计数、布尔值):用 @State。
-
子视图修改父视图的状态:用 @Binding。
-
对象(类)状态 且 多个视图共享:用 @Bindable(iOS 17+)。
-
iOS 16 及以下,用 @ObservedObject 代替 @Bindable(结合 ObservableObject)。