Two-way Bindings in SwiftUI
Bindings
and Observables
are essential for the basic SwiftUI
mechanism. One-way bindings are easier, but what about two-way bindings? You want two values to set observers on each other and when one of them changes, it should also reflect that change in the other value.
In Xcode 13.x and iOS 15.x, Apple introduced a new and cleaner way to provide two-way bindings without much hassle. Let's take a look at them with an example.
We have an app that shows the list of places with related information such as icons and names. The user can edit the nickname with any value they want. We also provide the "View Nicknames" button for all the list items which will show the list of updated nicknames for all the places after the edit operation is complete.
Every time the user edits the place's nickname and taps on the "View Nicknames" button, the app will display an alert with the list of edited nicknames.
Here are the basic building blocks of the app,
- We have a
Place
object with name, image, and nickname - Users can edit nicknames in the list
- The app will show the alert dialogue with edited nicknames when the user taps the "View Nicknames" button
import SwiftUI
struct Place: Identifiable {
let name: String
let imageName: String
var nickname: String
var id: String {
name
}
}
struct ContentView: View {
@State var places = [
Place(name: "Mumbai", imageName: "car", nickname: "placeholder"),
Place(name: "Vienna", imageName: "airplane", nickname: "placeholder"),
Place(name: "Amsterdam", imageName: "camera", nickname: "placeholder")
]
@State private var showingAlert = false
var body: some View {
VStack {
List {
ForEach($places) { $place in
VStack {
HStack {
Image(systemName: place.imageName)
Text(place.name)
TextField("Nickname", text: $place.nickname)
}
}
}
let nicknames = places.map { $0.nickname }.joined(separator: "\n")
Button("View Nicknames") {
showingAlert = true
}.alert(nicknames, isPresented: $showingAlert) {
Button("OK", role: .cancel) { }
}
}
}
}
}
The new syntax allows us to pass binding in the collection that gets attached to the editing TextField
. Every time the text field is edited, it gets updated in the original list of places too since they are attached by the two-way binding.
$
signLet's see the demo now,
And that's it. We successfully achieved the two-way bindings in the collection list!
Summary
This was all about how to achieve the two-way bindings in the collection list using new binding syntax for list-based closures. Two-way bindings is a powerful tool to create apps using an intuitive and readable format. I have used them many times in existing SwiftUI apps and they proved to be much useful to save time for initial development and future maintenance.
As usual, if you have any feedback or comments about this article, please reach out on Twitter at @jayeshkawli.