我对 swift 开发非常陌生,我正在尝试遵循多个不同的在线教程来尝试构建登录页面。不幸的是,所有不同的视图和模型都没有很好地整合在一起,我遇到了一些问题。
除了 ErrorView 显示之外,下面的代码似乎有效。当变量 alert 和 error 是 @Published 变量时,此代码不会编译。它给了我错误“无法为表达式生成诊断”。当我将它们都更改为 @State 变量时,它们不会更新视图。
class AppViewModel: ObservableObject{
@Published var signedIn = false
@Published var alert = false;
@Published var error = ""
let auth = Auth.auth();
func signIn(email: String, password: String){
auth.signIn(withEmail: email, password: password) { [weak self] result, error in
guard result != nil, error == nil else{
self?.error = error!.localizedDescription
print(error!.localizedDescription)
self?.alert.toggle()
return
}
DispatchQueue.main.async {
self?.signedIn = true
}
}
}
}
struct SignInView: View {
@State var email = ""
@State var password = ""
@EnvironmentObject var viewModel: AppViewModel
var body: some View {
VStack {
if viewModel.alert {
//SHOW ERROR
ErrorView(alert: viewModel.$alert, error: viewModel.$error)
Text("errors")
}
//SHOW SIGN IN FORM
//THERE IS CODE HERE TO CALL THE AUTH FUNCTIONS VIA BUTTONS ETC BUT APPARENTLY I'M NOT ALLOWED TO PUT THE WHOLE FILE IN THIS QUESTION
}
}
}
如果我使用已发布的变量,我会在 Failed to produce diagnostic for expression; please file a bug report
处收到错误 var body: some View
。如果我使用状态变量,则永远不会显示 ErrorView。
答案 0 :(得分:4)
您应该将 viewModel.$alert
更改为 $viewModel.alert
。
当您使用 @State
时,viewModel.$alert
的类型是 Binding<Bool>
。现在您已将其更改为 @Published
,就像它应该的那样,该类型现在是 Published<Bool>.Publisher
。
当您使用 $viewModel.alert
时,类型再次正确为 Binding<Bool>
。
答案 1 :(得分:1)
改变这个
ErrorView(alert: viewModel.$alert, error: viewModel.$error)
到这里
ErrorView(alert: $viewModel.alert, error: $viewModel.error)
几乎总是,您应该将任何变量移动到您的视图模型中。例如,您的视图中有 email and password
作为 @State 变量。将它们移动到您的视图模型更有意义。为什么?您稍后可能需要在 VM 本身的函数或方法中访问它们。如果数据已经存在,则处理起来要容易得多。在您看来,您可以使用 Text(viewModel.email)
或 Text(viewModel.password)
访问它。但是,如果您需要验证这一点,在您的视图模型中,它将很容易访问。