Use a dedicated network service.
Search your feelings, you know it to be true.
The problem is, it goes against everything you think you know about MVVM.
Most MVVM devs use view model as a convenient wrapper for networking requests (which have side effects), business logic, and view controls.
The idea behind it is to refactor out view-binding model and associated logic/effects.
And as with all design patterns, some devs would abuse it, twist it, copy and paste it from java ... etc.
As time goes by, devs began to take ViewModel for granted, since it's a norm in Android, it must work in iOS, right?
Any dev worth their salt would ask these questions when they try to port MVVM to SwiftUI:
Is there a binding mechanism in SwiftUI? How does it work?
struct Model: View {...}
, is this a model-view mapping? If so I may not need to declare
a separate ViewModel? (pro only question)
Whoever conforms to ObservableObject can be observed (to trigger view update), this goes
beyond the narrow definition of view model (view-related properties). An ObservableObject
can be a service or shared resource. E.g.; A networking service. Congratulations, you
just took the first step into a much larger world.
Why would I introduce a reference type view model to augment a value type model view for
every such value type that conforms to View in a SDK built around value type? Swift is not
java?
Now we have enough setup to properly answer your question.
Create a dedicated networking service, e.g.;
final class Resource: ObservableObject { // don't even need inheritance, OOP isn't always the best solution in all situations
@Published var requests = [Requests]()
// publish other resources
func loadRequests() {
/* update requests in callback */
}
}
use it, e.g.;
struct Model: View {
@State var model = MyModel() // can be "view model", because it maps to view
@EnvironmentObject var res: Resource
// or as an alternative, @ObservedObject var res = Resource()
var body: some View {
// access the automatic binding provided by SwiftUI, e.g.; res.requests
// call res.loadRequests() to mutate internal state of a reference type
// note that stateful part of the "view model" is refactored out
// so that `model` can be value type, yet it provides binding via @State
// instead of ObservableObject, which has to be reference type
// this is the brilliance of SwiftUI, it moves heaven and earth so you have
// the safety of immutability from value type, **unlike MVVM**
}
}
Done.
Why do we need ViewModel again? Let me know in the comments.