I am trying to understand the MVVM pattern in SwiftUI, but I am not understanding exactly how the ViewModel listens to and propagates changes from a Model object. Many examples, including this one from Apple, talk about having a Model inherit from ObservableObject and use that directly in your View. This makes sense.
But what is the best/recommended way that a ViewModel should observe changes to its underlying Model?
A simple example is a WidgetView that displays the title of a widget, but the title can change in the background from a background network call, for example.
class WidgetView: View {
@ObservedObject var widgetVM = WidgetViewModel()
var body: some View {
Text(widgetVM.title)
}
}
class WidgetViewModel : ObservableObject {
var widget: Widget
var title: String {
get {
// Some translation to the title for this particular view
return widget.title + "!"
}
}
}
struct Widget {
// Some other timer or background process is changing the title
var title: String
}
One rough solution I've explored is having a separate title and listening for changes. So if Widget extended ObservableObject and @Published the title field, then the WidgetViewModel could do the following:
class WidgetViewModel : ObservableObject {
var widget: Widget
@Published var title: String = ""
var cancellable: AnyCancellable?
init() {
self.cancellable = widget.$title.receive(on: DispatchQueue.main)
.sink(receiveValue: self.updateTitle )
}
func updateTitle(_: String) {
self.title = widget.title + "!"
}
}
Is it recommended/standard for Widget to extend ObservableObject too? If so, how does WidgetViewModel properly pass notifications of changes through? It would seem that WidgetModelView.widget would need to be both a @Published and an @ObservedObject, but that doesn't seem right.
Anyone have any insight here?