I want to decouple my ViewModel and View layer to increase testability of my Views. Therefore, I want to keep my property states inside view and only init them as I needed. But I cannot initialize my @Binding or @States with @Published properties. Is there a way to couple them inside init function?
I just add example code below to
instead of
import SwiftUI
class ViewModel: ObservableObject {
@Published var str: String = "a"
@Published var int: Int = 1 { didSet { print("ViewModel int = \(int)")} }
init() {
print("ViewModel initialized")
}
}
struct ContentView: View {
@ObservedObject vM = ViewModel()
var body: some View {
Button(action: { vM.int += 1; print(int) }, label: {
Text("Button")
})
}
}
I want to achieve this without using @ObservedObject inside my view.
import SwiftUI
class ViewModel: ObservableObject {
@Published var str: String = "a"
@Published var int: Int = 1 { didSet { print("ViewModel int = \(int)")} }
init() {
print("ViewModel initialized")
}
}
struct ContentView: View {
@Binding var str: String
@Binding var int: Int
var body: some View {
Button(action: { int += 1; print(int) }, label: {
Text("Button")
})
}
}
extension ContentView {
init(viewModel:ObservedObject<ViewModel> = ObservedObject(wrappedValue: ViewModel())) {
// str: Binding<String> and viewModel.str: Published<String>.publisher
// type so that I cannot bind my bindings to viewModel. I must accomplish
// this by using @ObservedObject but this time my view couples with ViewModel
_str = viewModel.wrappedValue.$str
_int = viewModel.wrappedValue.$int
print("ViewCreated")
}
}
// Testing Init
ContentView(str: Binding<String>, int: Binding<Int>)
// ViewModel Init
ContentView(viewModel: ViewModel)
This way I can't bind them each other, I just want to bind my binding or state properties to published properties.