Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind an EnvironmentObject variable to a slider

Tags:

swiftui

I have a sliderVal that needs to be accessed in various other places, so my understanding is that I should use a EnvironmentObject (or BindableObject, but EnvironmentObject was nice because this is used in the subviews as well) to hold those values. Something like this

struct ExampleView : View {

    @EnvironmentObject var externalData : ExternalData

    var body: some View {
        Slider(value: self.externalData.$sliderVal, from: 1, through: 100, by: 1)
    }

}

final class ExternalData : BindableObject {

    let didChange = PassthroughSubject<ExternalData, Never>()

    var sliderVal : Double = 5.0 {
        didSet {
            didChange.send(self)
        }
    }
}

This usually works for things like Text, however here, when I try to use the $ symbol to bind to something like a Slider, it gives a compile error of

Value of type 'ExternalData' has no member '$sliderVal'; did you mean 'sliderVal'?

But using just sliderVal gives me the error

Cannot convert value of type 'Double' to expected argument type 'Binding<_>'

Trying to use @State for sliderVal in my enviroment object builds successfully, but gives me this error at runtime

Fatal error: Accessing State<Double> outside View.body

Which makes since since @State things should be private.

What is the correct way to do this? I need to be able to access the sliderVal outside my view on a separate thread, so using a @Binding or @State doesn't work

like image 218
Phylliida Avatar asked Jan 26 '23 03:01

Phylliida


1 Answers

I found an answer here, the trick is to move the $ and not use self:

struct ExampleView : View {

    @EnvironmentObject var externalData : ExternalData

    var body: some View {
        Slider(value: $externalData.sliderVal, from: 1, through: 100, by: 1)
    }

}

final class ExternalData : BindableObject {

    let didChange = PassthroughSubject<ExternalData, Never>()

    var sliderVal : Double = 5.0 {
        didSet {
            didChange.send(self)
        }
    }
}
like image 132
Phylliida Avatar answered Jan 30 '23 01:01

Phylliida