Learn how to work with Xcode Previews in SwiftData App. SwiftData in combination with SwiftUI…
Differences between @Binding and @Bindable in SwiftUI
Binding – is a property wrapper used in SwiftUI to create a two-way binding between a view and its underlying data source. It allows you to link UI elements directly to state or model properties managed elsewhere, ensuring that changes in the UI update the data, and vice versa, without owning the data.
- Usage Example: If you have a settings screen where toggles reflect and control settings stored in the main app environment,
@Binding
lets you modify those settings directly from the toggles.
Bindable – is a property wrapper that simplifies the process of creating two-way bindings directly to properties of observable objects. It’s used to bind UI components directly to the properties of a model that conforms to theObservable
protocol, enabling straightforward management of model updates from the UI.
- Usage Example: In a form where you need to edit a user profile with fields like name and email,
@Bindable
allows the text fields to bind directly to theUserProfile
object’s properties, making the code cleaner and more manageable.
In essence, while @Binding
acts as a reference to link UI components to data managed elsewhere, @Bindable
provides a more direct and less verbose way to bind UI components to observable object properties.
Example Setup
Suppose we have a simple data model for a user profile that we want to display and edit in different views.
User Profile Model
import SwiftUI
@Observable
class UserProfile {
var name: String
init(name: String) {
self.name = name
}
}
Using @Binding
First, we’ll use @Binding
to create a child view that can edit the name in the UserProfile
.
struct ProfileEditorBinding: View {
@Binding var name: String
var body: some View {
TextField("Enter name", text: $name)
.padding()
.border(Color.gray)
}
}
struct ParentViewBinding: View {
@State var userProfile = UserProfile(name: "John Doe")
var body: some View {
VStack {
Text("Profile name: \(userProfile.name)")
ProfileEditorBinding(name: $userProfile.name)
}
}
}
Here, ProfileEditorBinding
does not own the name
data; it merely binds to it, allowing for changes that reflect back in the ParentViewBinding
.
Using @Bindable
Next, we’ll use @Bindable
in a similar setup but with a slightly different approach:
struct ProfileEditorBindable: View {
@Bindable var userProfile: UserProfile
var body: some View {
TextField("Enter name", text: $userProfile.name)
.padding()
.border(Color.gray)
}
}
struct ParentViewBindable: View {
@StateObject var userProfile = UserProfile(name: "Jane Doe")
var body: some View {
VStack {
Text("Profile name: \(userProfile.name)")
ProfileEditorBindable(userProfile: userProfile)
}
}
}
In this case, ProfileEditorBindable
uses @Bindable
to create a more direct and intuitive binding to the entire UserProfile
object. The view can bind directly to the properties of userProfile
, simplifying how data flows between the UI elements and the data model.
Key Differences Demonstrated
- @Binding: Best for when you need to share a specific piece of data between views without ownership, keeping views synchronized with a source of truth defined elsewhere.
- @Bindable: Useful for more direct interaction with multiple properties of an observable object, streamlining how properties are updated from the UI, especially when those properties are used across different views.
s
dfsdf