In the code below (a stripped-down version of some code in a project) I'm using a MVVM pattern with two views:
I'm also passing that computed value to a ViewModelB, using Binding, which acts as a StateObject for ViewB. However, when dragging the Slider to change that value, the value changes on ViewA but doesn't change on ViewB and the slider itself doesn't slide. As expected, when debugging, the wrappedValue inside the Binding is not changing.
But how is the change propagated upwards (through the Binding's setters, I imagine) but not downwards back to ViewB??
I imagine this means I'm breaking the single source of truth pattern I just don't know why.
Another question, kinda related to the example but this one regarding MVVM, supposedly the best pattern to use with SwiftUI:
I've only ever seen Binding being used inside Views with View specific properties, but if I stick with mvvm in which the connection between View and Model should be made through the ViewModel, so if I want to change a value stored in a Model with information used throughout an application with, for example, a slider, the only options I see are either using only one ViewModel per Model (which might make the ViewModel too big if I have many views that can change the Model in different ways), or having to pass the Model (or it's properties) between ViewModels through Binding (and I don't see why not). Or am I missing something?
In the Data Essentials in SwiftUI session in WWDC20 they use a diagram that seem to represent mvvm with several ViewModels for the same data model but the use of value types makes it confusing for me how children views' ViewModels could access data stored in ViewModels of parent views.
I've also thought of the possibility of using some sort of Repository or some class that encapsulates the data model in a reference type that could be passed around between Views/ViewModels maybe using EnvironmentObject but that, apart from other problems like using @Published with reference types, feels like a workaround that goes against the natural flow of Swift's value types.
I can see MVVM being useful for simple(-ish) view hierarchies and data models, but because of what I mentioned above it doesn't seem like Swift and SwiftUI's support for ir is a bit more limited for slightly more complex cases.
Sorry for the long post and thanks in advance!
Views:
ViewModels:
Model:
ViewA - displays a value stored in an ObservableObject ViewModel;
ViewB - displays the same value and has a Slider that changes that value, which is passed to the view using Binding.
I'm also passing that computed value to a ViewModelB, using Binding, which acts as a StateObject for ViewB. However, when dragging the Slider to change that value, the value changes on ViewA but doesn't change on ViewB and the slider itself doesn't slide. As expected, when debugging, the wrappedValue inside the Binding is not changing.
But how is the change propagated upwards (through the Binding's setters, I imagine) but not downwards back to ViewB??
I imagine this means I'm breaking the single source of truth pattern I just don't know why.
Another question, kinda related to the example but this one regarding MVVM, supposedly the best pattern to use with SwiftUI:
I've only ever seen Binding being used inside Views with View specific properties, but if I stick with mvvm in which the connection between View and Model should be made through the ViewModel, so if I want to change a value stored in a Model with information used throughout an application with, for example, a slider, the only options I see are either using only one ViewModel per Model (which might make the ViewModel too big if I have many views that can change the Model in different ways), or having to pass the Model (or it's properties) between ViewModels through Binding (and I don't see why not). Or am I missing something?
In the Data Essentials in SwiftUI session in WWDC20 they use a diagram that seem to represent mvvm with several ViewModels for the same data model but the use of value types makes it confusing for me how children views' ViewModels could access data stored in ViewModels of parent views.
I've also thought of the possibility of using some sort of Repository or some class that encapsulates the data model in a reference type that could be passed around between Views/ViewModels maybe using EnvironmentObject but that, apart from other problems like using @Published with reference types, feels like a workaround that goes against the natural flow of Swift's value types.
I can see MVVM being useful for simple(-ish) view hierarchies and data models, but because of what I mentioned above it doesn't seem like Swift and SwiftUI's support for ir is a bit more limited for slightly more complex cases.
Sorry for the long post and thanks in advance!
Views:
Code Block import SwiftUI struct ContentView: View { @StateObject var viewModelA = ViewModelA() var body: some View { VStack{ ViewA(value: viewModelA.value) ViewB(value: $viewModelA.value) } } } struct ViewA: View { let value: Double var body: some View { Text("\(value)").padding() } } struct ViewB: View { @StateObject var viewModelB: ViewModelB init(value: Binding<Double>){ _viewModelB = StateObject(wrappedValue: ViewModelB(value: value)) } var body: some View { VStack{ Text("\(viewModelB.value)") Slider(value: $viewModelB.value, in: 0...1) } } }
ViewModels:
Code Block class ViewModelA: ObservableObject { @Published var model = Model() var value: Double { get { model.value } set { model.value = newValue /* perform other checks and operations */ } } } class ViewModelB: ObservableObject { @Binding var value: Double init(value: Binding<Double>){ self._value = value } }
Model:
Code Block struct Model { var value: Double = 0 }