Harry Day
Harry Day

Reputation: 408

SwiftUI and Combine - Update variable in view model when another changes

I am currently building a small one view app to help learn some more SwiftUI. The app is a simple app to calculate values in a ratio. I have 4 main variables at the moment, the left and right side of the ratio, and the first and second value that will be calculated in ratio. Initially I had each of these stored as @State properties:

@State var leftSide = Double()
@State var rightSide = Double()
@State var value1 = Double()
@State var value2 = Double()

In the app there are 4 sliders that allow each variable to be changed independently of each other. What I want to now allow to happen is that changing the variable value1 will also update value2 according to the ratio the user has set. To achieve this I believe I need to use Combine however I have not got much experience with the framework.

To begin with I moved the variables to an ObservableObject class:

final class UserData: ObservableObject {
    @Published var leftSide = Double()
    @Published var rightSide = Double()
    @Published var value1 = Double()
    @Published var value2 = Double()
}

I updated my main view with @ObservedObject var userData = UserData() so I could access the variables in my view and this works fine

Now I want to update the value1 and value2 variables when the other changes. From the reading I have done I think I need to use a subscriber but I cannot find anything on how to set this up with they @Published property. Have I gone about this in the correct way or is there a better way to do this?

Upvotes: 3

Views: 3300

Answers (1)

user3441734
user3441734

Reputation: 17572

I have 4 main variables at the moment, the left and right side of the ratio, and the first and second value that will be calculated in ratio

so, why you don't declare it as computed variables?

final class UserData: ObservableObject {
    @Published var leftSide = 0.0
    @Published var rightSide = 0.0
    var value: Double {
        // perform the calculation here
        ...
    }
}

If you like to change value independently (bind it to SwiftUI component), and modify the value in case leftSide or rightSide are modified, use willSet or even didSet

final class UserData: ObservableObject {
    @Published var leftSide = 0.0 {
        willSet {
           // update value 
            value = f(newValue)
        }
        didSet {
           // update value
           value = f(oldValue)
        }
    }
    @Published var rightSide = 0.0
    @Published var value = 0.0
    func f(_ v: Double)->Double {
        ......
    }
}

Upvotes: 2

Related Questions