【问题标题】:SwiftUI @State variable not updating viewSwiftUI @State 变量不更新视图
【发布时间】:2021-08-06 19:05:37
【问题描述】:

我对快速开发非常陌生,我正在尝试遵循多个不同的在线教程来尝试构建登录页面。不幸的是,所有不同的视图和模型都没有很好地结合在一起,我遇到了一些问题。

除了显示的 ErrorView 之外,下面的代码似乎可以工作。当变量 alerterror 是 @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
        }
    }
}

如果我使用已发布的变量,我会在 var body: some View 处收到错误 Failed to produce diagnostic for expression; please file a bug report。如果我使用状态变量,则永远不会显示 ErrorView。

【问题讨论】:

  • 您需要edit 您的问题以minimal reproducible example 的形式包含所有相关代码,以便使问题成为主题。您的问题中有太多代码,这使得其他人更难查明问题。
  • @DávidPásztor 我现在已经这样做了。
  • 该错误意味着您的代码以某种编译器无法识别的方式损坏。我建议在编译之前对代码块进行注释,以便找出有问题的块在哪里。除此之外,我们无法从该错误消息中找出很多信息。
  • @ArianeHine 没有ErrorView,我们无法解决问题。您的意思是 $viewModel.alert 而不是 viewModel.$alert
  • 您还应该尝试为每个重要的View 创建适当的Swift 文件

标签: swift swiftui


【解决方案1】:

您应该将viewModel.$alert 更改为$viewModel.alert

当您使用@State 时,viewModel.$alert 的类型为Binding<Bool>。现在您已将其更改为 @Published,就像它应该的那样,该类型现在是 Published<Bool>.Publisher

当你使用$viewModel.alert时,类型又是Binding<Bool>了。

【讨论】:

    【解决方案2】:

    改变这个

    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) 访问它。但是,如果您需要在您的视图模型中验证这一点,它将很容易访问。

    【讨论】:

      猜你喜欢
      • 2020-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多