What is SwiftUI @Binding?


@Binding is a crucial property wrapper that allows you to create a two-way connection between a value stored in one view and a property in another view.


Why do we need @Binding?

SwiftUI views are generally designed to be lightweight and to derive their content from their state.

When a view needs to pass data down to a child view, and that child view needs to be able to modify that data and have the parent view react to those changes, @Binding comes into play.


The problem without @Binding:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct ParentView: View {
    @State private var counter = 0 // Source of truth
 
    var body: some View {
        VStack {
            Text("Parent Counter: \(counter)")
            ChildView(value: counter) // Passing 'counter' by value (a copy)
        }
    }
}
 
struct ChildView: View {
    var value: Int // Receives a copy of the counter
 
    var body: some View {
        Button("Increment in Child") {
            // value += 1 // ERROR: Cannot assign to property: 'value' is a 'let' constant (or even if it's a var, it's a copy!)
        }
    }
}
cs

In this scenario, ChildView receives a copy of counter. Even if you make value a var, modifying it within ChildView would only change that local copy, and the ParentView's counter would remain unchanged.


How @Binding solves this:

@Binding allows the child view to directly manipulate the parent's @State

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import SwiftUI
 
struct ParentView: View {
    @State private var counter = 0 // This is the single source of truth
 
    var body: some View {
        VStack {
            Text("Parent Counter: \(counter)")
            // Pass a binding to the child using '$'
            ChildView(value: $counter)
        }
    }
}
 
struct ChildView: View {
    @Binding var value: Int // Declared as a @Binding, receives a reference
 
    var body: some View {
        Button("Increment in Child") {
            value += 1 // This now directly modifies the 'counter' in ParentView!
        }
    }
}
cs

If value is modified in ChildView, counter in ParentView is immediately updated, and any view that depends on counter will re-render.

If counter is modified in ParentView, value in ChildView is also immediately updated, and ChildView will re-render if it depends on value.


++) @Binding vs @State vs @ObservedObject / @StateObject

- @State: Owns a simple value type (structs, enums, basic types like Int, String, Bool).

It's the source of truth for local view state.

- @ObservedObject / @StateObject: Owns a reference type (class conforming to ObservableObject).

It's the source of truth for complex object models. (@StateObject for ownership, @ObservedObject for observing already-owned objects).

- @Binding: Does not own data. It provides a two-way connection to a source of truth owned elsewhere. It's how child views manipulate data owned by their parents.