You’ve learned two ways to implement one-way binding between views and a view model, where a view needs only read-access to a view model object. The next question is, what do you need to do to get two-way binding, where a view can update a value in the view model object? Consider these three cases.
@State in View
You declare and instantiate the view model object in the view. Then somewhere in this view, you want to modify a value in the view model object. The easiest case is to use a binding to the view model object. For example, the view model object has a collection of objects that the view displays in a List, and you want to modify a property of an object in the list:
@State var store = TheMetStore()
...
List($store.objects, id: \.objectID) { $object in
...
object.isFavorite.toggle()
Passed to View
You declare and instantiate the view model object in a view or in the app struct, then pass it as a parameter to a subview. In the subview, declare the view model object as @Bindable:
// In TheMetApp
struct TheMetApp: App {
@State var store = TheMetStore()
var body: some Scene {
WindowGroup {
ContentView(store: store)
}
}
}
// In ContentView
struct ContentView: View {
@Bindable var store: TheMetStore
...
List($store.objects, id: \.objectID) { $object in
...
object.isFavorite.toggle()
@Environment
You declare and instantiate the view model object in the app struct or in a view, then inject it into the environment of the app or the parent view’s subtree. An environment object is read-only, but you can create a @Bindable version of it in the view:
// In TheMetApp
struct TheMetApp: App {
@State var store = TheMetStore()
var body: some Scene {
WindowGroup {
ContentView()
.environment(store)
}
}
}
// In ContentView
@Environment(TheMetStore.self) var store
...
VStack {
@Bindable var twoWayStore = store
...
List($twoWayStore.objects, id: \.objectID) { $object in
...
NavigationLink(object.title) {
ObjectView(object: $object) // ObjectView modifies object.isFavorite
}
Giqwax agacj kald bli zila jikiu xe geo obd ug csiri or ahteug.
See forum comments
This content was released on Feb 28 2025. The official support period is 6-months
from this date.
Learn how to implement two-way binding in views and subviews.
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.