What is "@Binding" in SwiftUI?
@Binding
is an almost essential tool for developing apps with SwiftUI. Today, I will show what the @Binding
is and how to use it.
TL; DR
@Binding
is a property wrapper in SwiftUI that shares states from views. In many cases, it is used to pass a state of a property from a parent view to a child view.
Prerequisite
@Binding
has a strong relationship with @State
, so please check the article below first if you have no idea of @State
.
What is "@State" in SwiftUI?
This one will also help you understand binding
What @Binding
is
Let's see an example before I explain what it is:
struct ContentView: View {
@State var number = 1;
var body: some View {
VStack {
Text("The number is \(number) now.")
Button("Increment") {
number += 1
}
}
}
}
This is easy to understand. However, what if we want to create a decorated button as a new component and call it in the "ContentView"?
Someone who is not familiar with @Binding
might do:
❌ Incorrect approach
struct ContentView: View {
@State var number = 1
var body: some View {
VStack {
Text("The number is \(number) now.")
MyIncrementButton(number: number)
}
}
}
struct MyIncrementButton: View {
@State var number: Int
var body: some View {
Button("Increment") {
number += 1
}
.padding()
.background(Color(red: 0, green: 0, blue: 0.5))
.clipShape(Capsule())
}
}
With the code above, the "number" in the "Text" of the "ContentView" will not be updated; even if the button is clicked, the "number" will always be 1.
Instead, we have to modify the code like this:
⭕️ Correct approach
struct ContentView: View {
@State var number = 1
var body: some View {
VStack {
Text("The number is \(number) now.")
MyIncrementButton(number: $number)
}
}
}
struct MyIncrementButton: View {
@Binding var number: Int
var body: some View {
Button("Increment") {
number += 1
}
.padding()
.background(Color(red: 0, green: 0, blue: 0.5))
.clipShape(Capsule())
}
}
With the code, the "number" in the "Text" of the "ContentView" will be correctly updated with the button.
@Binding
creates a connection between the parent's @State
property and the child's property. We cannot share the state of properties from a child view to a parent view without the property wrapper @Binding
.
It is important to note that we must add the prefix "$" when passing a@State
property as a @Binding
parameter. The "$" indicates that you are passing a binding not its value. Because we have to pass a binding rather than value to @Binding
parameters, I added "$" to the @State
property.
It is also important to note that while @State
declare a mutable state property within a view, @Binding
creates a reference to a mutable state property.