SwiftData 教程与示例:将 SwiftData 对象与 SwiftUI 组件绑定(八)

了解如何将 SwiftUI 中支持双向绑定的组件(例如 Picker、TextField),绑定到 SwiftData 对象,并确保在数据更新时自动保存更新。

SwiftData 教程与示例:将 SwiftData 对象与 SwiftUI 组件绑定(八)

SwiftUI 提供了一些支持数据双向绑定(Two-Way Binding)的组件,例如 PickerTextFieldToggleSlider 等。这种绑定机制允许数据模型与 UI 组件之间相互更新,当组件的值发生更改时,绑定的属性值自动更新;反之亦然。我们不需要手动设置回调或侦听器来更新 UI,SwiftUI 会自动管理绑定。

因此,我们有两个疑问:

  • 是否可以将 SwiftData 对象绑定到 SwiftUI 的组件上(如 Picker)?
  • 当数据更新时,SwiftData 数据是否会自动保存?

答案是肯定的,你可以将 SwiftData 对象与 SwiftUI 组件绑定,并且数据更新时可以自动保存——这是 SwiftData 的核心优势之一。

SwiftData 对象与 SwiftUI 组件的绑定

举例来说,假设有一个 SwiftData 对象属性 selectedOption,可以直接将其绑定到 Picker 的选择值上:

@Query var dataObject: MyDataModel

然后在 Picker 中绑定 dataObject.selectedOption

Picker("选择", selection: $dataObject.selectedOption) {
    Text("选项1").tag(1)
    Text("选项2").tag(2)
    Text("选项3").tag(3)
}

在这种情况下,每当 Picker 更新选择值时,SwiftData 数据模型中的 selectedOption 也会自动更新。

数据如何自动保存

SwiftData 提供了一个 autosaveEnabled 属性,用于指示 SwiftData 上下文是否在发生某些事件时,自动保存任何待处理的更改。

autosaveEnabled | Apple Developer Documentation
A Boolean value that indicates whether the context should automatically save any pending changes when certain events occur.

SwiftData 默认将主 mainContext 的 autosaveEnabled 属性设置为 true,这就是会自动保存的原因。

父组件与子组件间的对象传递与绑定

💡
待修改为 @Bindable,而不是@Binding

在父组件中获取的 SwiftData 对象,当需要在子组件中传递并绑定 SwiftUI 组件以便能够修改时,必须使用 @Binding

在 SwiftUI 中,支持双向绑定的组件,只能绑定被以下属性包装器之一标记的变量:

  • @State
  • @Binding
  • @ObservedObject
  • @EnvironmentObject

@State 用于结构体内部私有变量,不建议用于外部数据传递。因此,使用最多的是 @Binding

例如:

struct ParentView: View {
    @Query var dataObject: MyDataModel

    var body: some View {
        ChildView(dataObject: dataObject)
    }
}

若子组件需要更改父组件中的数据(如更新 Picker 选择值),则应该使用 @Binding 将数据绑定传递给子组件,以确保数据双向绑定。

struct ChildView: View {
    @Binding var dataObject: MyDataModel
}