Binding value from an ObservableObject

Aim:

I have a model which is an

ObservableObject
. It has a
Bool
property, I would like to use this
Bool
property to initialise a
@Binding
variable.

Questions:

  1. How to convert an
    @ObservableObject
    to a
    @Binding
    ?
  2. Is creating a
    @State
    the only way to initialise a
    @Binding
    ?

Note:

  • I do understand I can make use of
    @ObservedObject
    /
    @EnvironmentObject
    , and I see it's usefulness, but I am not sure a simple button needs to have access to the entire model.
  • Or is my understanding incorrect ?

Code:

import SwiftUI
import Combine
import SwiftUI
import PlaygroundSupport

class Car : ObservableObject {

  @Published var isReadyForSale = true
}

struct SaleButton : View {

  @Binding var isOn : Bool

  var body: some View {

  Button(action: {

  self.isOn.toggle()
  }) {
  Text(isOn ? "On" : "Off")
  }
  }
}


let car = Car()

//How to convert an ObservableObject to a Binding
//Is creating an ObservedObject or EnvironmentObject the only way to handle a Observable Object ?

let button = SaleButton(isOn: car.isReadyForSale) //Throws a compilation error and rightly so, but how to pass it as a Binding variable ?

PlaygroundPage.current.setLiveView(button)
  • how can you bind a function

Add a Comment

Accepted Reply

ObservableObject will provide you with a binding to any contained property automatically via the $-prefix syntax:


class Car: ObservableObject {
    @Published var isReadyForSale = true
}

struct SaleView: View {
    @Binding var isOn: Bool

    var body: some View {
        Toggle("Ready for Sale", isOn: $isOn)
    }
}

struct ContentView: View {
    @ObservedObject var car: Car

    var body: some View {
        Text("Details")
            .font(.headline)
        SaleView(isOn: $car.isReadyForSale)  // generates a Binding to 'isReadyForSale' property
    }
}
  • From this example, it appears that you can only create a binding from @ObservedObject, rather than ObservableObject.

Add a Comment

Replies

Binding has an initializer which accepts getter and setter closures.


We can use the getter and setter to access and update the model.


let button = SaleButton(isOn: Binding(get: {car.isReadyForSale}, set: { car.isReadyForSale = $0 }))


Refer: https://developer.apple.com/documentation/swiftui/binding/3363053-init

  • This is one of those golden eggs sir. Comes in handy when testing a view and need to pass an arbitrary Binding.

Add a Comment

ObservableObject will provide you with a binding to any contained property automatically via the $-prefix syntax:


class Car: ObservableObject {
    @Published var isReadyForSale = true
}

struct SaleView: View {
    @Binding var isOn: Bool

    var body: some View {
        Toggle("Ready for Sale", isOn: $isOn)
    }
}

struct ContentView: View {
    @ObservedObject var car: Car

    var body: some View {
        Text("Details")
            .font(.headline)
        SaleView(isOn: $car.isReadyForSale)  // generates a Binding to 'isReadyForSale' property
    }
}
  • From this example, it appears that you can only create a binding from @ObservedObject, rather than ObservableObject.

Add a Comment