About @State and @Binding
Imagine a situation where you have two SwiftUI views. In the first view you have declared a count
property, and in the second one, you have created a Tap Me
button. When the button is tapped, the value of count
in the first view should be updated. To implement this logic, you need a @State
property wrapper in the first view and a @Binding
property wrapper in the second one.
@State
allows locally manipulate small amounts of data of value type
. @State
creates and manages values directly, so it's a Source of Truth
. @Binding
also refers to data of value type
but owned by a different view. @Binding
is not a source of truth. In order to feed the @State
property to Binding<T>
you need to use the $
operator (i.e. it'll look like $count
). @Binding
creates a two-way connection between a property and another view.
Here's the code:

import SwiftUI
struct FirstView: View {
@State private var count: Int = 0
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
VStack {
SecondView(counter: $count).frame(width: 300, height: 100)
Text("Tapped \(count) times").foregroundColor(.white)
}
}
}
}
struct SecondView: View {
@Binding var counter: Int
var body: some View {
ZStack {
Color.yellow
Text("Tap Me").onTapGesture { counter += 1 }
}
}
}
Besides the aforementioned property wrappers, a similar result can be achieved with the help of so-called "trinity"-kit – @StateObject
, @Published
and @ObservedObject
.
Property Wrappers
The following pivot table represents three main characteristics (Source of Truth, purpose and semantics) of 17 commonly used SwiftUI 4.0 property wrappers.
# |
Property Wrapper |
Source of Truth |
What it's for? |
Semantics |
01 |
@AppStorage |
Yes |
reads/writes from UserDefaults |
value |
02 |
@Binding |
no |
creates a two-way connection |
value |
03 |
@Environment |
no |
reads data from the system |
value |
04 |
@EnvironmentObject |
no |
reads a shared object from multiple views |
reference |
05 |
@FetchRequest |
Yes |
use it for CoreData fetch request |
value |
06 |
@FocusedBinding |
no |
observing & unwrapping state bindings from the focused view |
value |
07 |
@FocusedValue |
no |
simpler version of @FocusedBinding |
value |
08 |
@GestureState |
Yes |
stores values of active gesture |
value |
09 |
@Namespace |
Yes |
is a wrapper for namespace.id that prevents name collision |
value |
10 |
@ObservedObject |
no |
refers to instance of external class that conforms to ObservableObject |
reference |
11 |
@Published |
Yes |
is attached to properties inside ObservableObject |
value |
12 |
@ScaledMetric |
Yes |
allow app views to scale given user's Dynamic Type settings |
value |
13 |
@SceneStorage |
Yes |
restores system state's lightweight data |
value |
14 |
@State |
Yes |
manipulates view's data locally |
value |
15 |
@StateObject |
Yes |
stores a new instance that conforms to ObservableObject |
reference |
16 |
@NSApplicationDelegateAdaptor |
Yes |
creates an AppKit app delegate |
protocol |
17 |
@UIApplicationDelegateAdaptor |
Yes |
creates an UIKit app delegate |
protocol |
How to...
The following are examples of how you can use four popular property wrappers.