Home > Software engineering >  How to pass Binding of @published variable in function from ObservedObject
How to pass Binding of @published variable in function from ObservedObject

Time:12-20

I want to pass a binding of a @Published variable from within my ObservableObject to a struct so that its value can be changed inside a closure. I can't quite get it to work. Here is a simplified version of my code below:

final class OnboardingStateController: ObservableObject {
  @Published var shouldHide: Bool = false

  func go() {
    MyLogic.fooBar(
      shouldHide: shouldHide // error appears here Cannot convert value of type 'Bool' to expected argument type 'Binding<Bool>'
    )
  }
}

struct MyLogic {
  static func fooBar(shouldHide: Binding<Bool>) {
    ... SomeClass({ shouldHide.wrappedValue = true })
  }
}

How do I do this?

CodePudding user response:

Here is an alternative, Binding needs a SwiftUI View to stay updated because of its DynamicProperty conformance

import SwiftUI

struct OnboardingStateView: View {
    @StateObject var vm: OnboardingStateController = OnboardingStateController()
    var body: some View {
        VStack{
            Button("go", action: {
                vm.go()
            })
            Text(vm.shouldHide.description)
        }
    }
}
final class OnboardingStateController: ObservableObject {
    @Published var shouldHide: Bool = false
    
    func go() {
        //This uses a completion handler vs passing the `Binding`
        MyLogic.fooBar(
            shouldHide: { shouldHide in
                self.shouldHide = shouldHide
            }
        )
    }
}

struct MyLogic {
    static func fooBar(shouldHide: (Bool) -> Void) {
        let value = Bool.random() //.. SomeClass({ shouldHide.wrappedValue = true })
        shouldHide(value)
    }
}

struct OnboardingStateView_Previews: PreviewProvider {
    static var previews: some View {
        OnboardingStateView()
    }
}

CodePudding user response:

It is not really clear why do you need Binding there, but if it is really still needed there, then you can generate it on the fly, like

  func go() {
    MyLogic.fooBar(
      shouldHide: Binding(get: { self.shouldHide }, set: { self.shouldHide = $0 })
    )
  }

Note: it is simplified variant, in which self is captured, if you need to avoid it then you take into account using [weak self] in each closure.

  • Related