Binding value from an ObservableObject
You have several options to observe the
ObservableObject
. If you want to be in sync with the state of the object, it's inevitable to observe the state of the stateful object. From the options, the most commons are:@State
@ObservedObject
@EnvironmentObject
It is upto you, which one suits your use case.
- No. But you need to have an object which can be observed of any change made to that object in any point in time.
In reality, you will have something like this:
class Car: ObservableObject {
@Published var isReadyForSale = true
}
struct ContentView: View {
// It's upto you whether you want to have other type
// such as @State or @ObservedObject
@EnvironmentObject var car: Car
var body: some View {
SaleButton(isOn: $car.isReadyForSale)
}
}
struct SaleButton: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
Text(isOn ? "Off" : "On")
}
}
}
If you are ready for the @EnvironmentObject
you will initialize your view with:
let contentView = ContentView().environmentObject(Car())
Binding
variables can be created in the following ways:
@State
variable's projected value provides aBinding<Value>
@ObservedObject
variable's projected value provides a wrapper from which you can get theBinding<Subject>
for all of it's properties- Point 2 applies to
@EnvironmentObject
as well. - You can create a Binding variable by passing closures for getter and setter as shown below:
let button = SaleButton(isOn: .init(get: { car.isReadyForSale },
set: { car.isReadyForSale = $0} ))
Note:
- As @nayem has pointed out you need
@State
/@ObservedObject
/@EnvironmentObject
/@StateObject
(added in SwiftUI 2.0) in the view for SwiftUI to detect changes automatically. - Projected values can be accessed conveniently by using
$
prefix.