What is "@Binding" in SwiftUI?

·

3 min read

@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.