When trying to compile the following code:
class LoginViewModel: ObservableObject, Identifiable {
@Published var mailAdress: String = ""
@Published var password: String = ""
@Published var showRegister = false
@Published var showPasswordReset = false
private let applicationStore: ApplicationStore
init(applicationStore: ApplicationStore) {
self.applicationStore = applicationStore
}
var passwordResetView: some View {
PasswordResetView(isPresented: $showPasswordReset) // This is where the error happens
}
}
Where PasswordResetView looks like this:
struct PasswordResetView: View {
@Binding var isPresented: Bool
@State var mailAddress: String = ""
var body: some View {
EmptyView()
}
}
}
I get the error compile error
Cannot convert value of type 'Published<Bool>.Publisher' to expected argument type 'Binding<Bool>'
If I use the published variable from outside the LoginViewModel class it just works fine:
struct LoginView: View {
@ObservedObject var viewModel: LoginViewModel
init(viewModel: LoginViewModel) {
self.viewModel = viewModel
}
var body: some View {
PasswordResetView(isPresented: self.$viewModel.showPasswordReset)
}
}
Any suggestions what I am doing wrong here? Any chance I can pass a published variable as a binding from inside the owning class?
Thanks!
Here is possible approach - the idea to make possible observation in generated view and avoid tight coupling between factory & presenter.
Tested with Xcode 12 / iOS 14 (for older systems some tuning might be needed)
protocol ResetViewModel {
var showPasswordReset: Bool { get set }
}
struct PasswordResetView<Model: ResetViewModel & ObservableObject>: View {
@ObservedObject var resetModel: Model
var body: some View {
if resetModel.showPasswordReset {
Text("Show password reset")
} else {
Text("Show something else")
}
}
}
class LoginViewModel: ObservableObject, Identifiable, ResetViewModel {
@Published var mailAdress: String = ""
@Published var password: String = ""
@Published var showRegister = false
@Published var showPasswordReset = false
private let applicationStore: ApplicationStore
init(applicationStore: ApplicationStore) {
self.applicationStore = applicationStore
}
var passwordResetView: some View {
PasswordResetView(resetModel: self)
}
}