Trying to go from UIKit to SwiftUI I keep wondering how to apply a service layer properly and use observables to publish updates from the service layer all the way out through the view model and to the view.
I have a View that has a View model, which derives from ObservableObject and publishes a property, displayed in the view. Using @EnvironmentObject I can easily access the view model from the view.
struct SomeView: View {
@EnvironmentObject var someViewModel: SomeViewModel
var body: some View {
TextField("Write something here", text: $someViewModel.someUpdateableProperty)
}
}
class SomeViewModel: ObservableObject {
@Published var someUpdateableProperty: String = ""
var someService: SomeService
init(someService: SomeService) {
self.someService = someService
}
// HOW DO I UPDATE self.someUpdateableProperty WHEN someService.someProperty CHANGES?
// HOW DO I UPDATE someService.someProperty WHEN self.someUpdateableProperty CHANGES?
}
class SomeService {
var someProperty: String = ""
func fetchSomething() {
// fetching
someProperty = "Something was fetched"
}
func updateSomething(someUpdateableProperty: String) {
someProperty = someUpdateableProperty
}
}
In my head a simple way could be to forward the property i.e. using computed property
class SomeViewModel: ObservableObject {
@Published var someUpdateableProperty: String {
get {
return someService.someProperty
}
set {
someService.someProperty = value
}
}
var someService: SomeService
init(someService: SomeService) {
self.someService = someService
}
}
Another approach could be if it was possible to set the two published properties equal to each other:
class SomeService: ObservableObject {
@Published var someProperty: String = ""
func fetchSomething() {
// fetching
someProperty = "Something was fetched"
}
}
class SomeViewModel: ObservableObject {
@Published var someUpdateableProperty: String = ""
var someService: SomeService
init(someService: SomeService) {
self.someService = someService
someUpdateableProperty = someService.someProperty
}
}
What is the correct way to forward a publishable property directly through a view model?
In UIKit I would use delegates or closures to call from the service back to the view model and update the published property, but is that doable with the new observables in SwiftUI?
*I know keeping the state in the service is not a good practice, but for the example let's use it.