枚举类型的 SwiftUi @State 变量为 nil

SwiftUi @State variable of type enum is nil

我有四个观点:

LoginView()
SignInWithEmailView()
SignUpView()
ForgotPasswordView()

LoginView:

struct LoginView: View {
    
    enum Action {
        case signUp, resetPW
    }

    @State private var showSheet = false
    @State private var action: Action?

    init() {
        print(self.action) //prints nil
    }
        
    var body: some View {
        VStack {
            SignInWithEmailView(showSheet: $showSheet, action: $action)
            SignInWithAppleView()
                .frame(width: 200, height: 50)
            Spacer()
        }
            .sheet(isPresented: $showSheet) {
                if self.action == .signUp {
                    SignUpView()
                } else {
                    ForgotPasswordView()
                }
            }
    }
}

SignInWithEmailView :

struct SignInWithEmailView: View {
    @EnvironmentObject var userInfo: UserInfo
    @State var user: UserViewModel = UserViewModel()
    @Binding var showSheet: Bool
    @Binding var action: LoginView.Action?
    
    @State private var showAlert = false
    @State private var authError: EmailAuthError?
    
    var body: some View {
        VStack {
            CustomTextField(secureInput: false, titleKey: "Email Address",
                      fieldText: self.$user.email)
                .autocapitalization(.none)
                .keyboardType(.emailAddress)
            CustomTextField(secureInput: true, titleKey: "Password", fieldText: $user.password)
            HStack {
                Spacer()
                Button(action: {
                    self.showSheet = true
                    self.action = .resetPW
                }) {
                    Text("Forgot Password")
                }
            }.padding(.bottom)
            VStack(spacing: 10) {
                FormButton(buttonText: "Login", buttonAction: {
                    FBAuth.authenticate(withEmail: self.user.email,
                                        password: self.user.password) { (result) in
                        switch result {
                        case .failure(let error):
                            self.authError = error
                            self.showAlert = true
                        case .success( _):
                            print("Signed in")
                        }
                    }
                })
                    .opacity(user.isLogInComplete ? 1 : 0.5)
                    .disabled(!user.isLogInComplete)
                
                FormButton(buttonText: "Sign UP", buttonAction: {
                    self.showSheet = true
                    self.action = .signUp
                })
            }
            .alert(isPresented: $showAlert) {
                Alert(title: Text("Login Error"), message: Text(self.authError?.localizedDescription ?? "Unknown error"), dismissButton: .default(Text("OK")) {
                    if self.authError == .incorrectPassword {
                        self.user.password = ""
                    }else {
                        self.user.email = ""
                        self.user.password = ""
                    }
                })
            }
        }
        .padding(.top, 100)
        .frame(width: 300)
        .textFieldStyle(RoundedBorderTextFieldStyle())
        
    }
}

SignUpView :

struct SignUpView: View {
    @EnvironmentObject var userInfo: UserInfo
    @State var user: UserViewModel = UserViewModel()
    @Environment(\.presentationMode) var presentationMode

    
    @State private var showError = false
    @State private var errorString = ""

    var body: some View {
        NavigationView {
            VStack {
                Group {
                    AvatarSelection()
                    VStack(alignment: .leading) {
                        CustomTextField(secureInput: false, titleKey: "Full Name", fieldText: self.$user.fullname)
                        if !user.validNameText.isEmpty {
                            Text(user.validNameText).font(.caption).foregroundColor(.red)
                        }

                    }
                    VStack(alignment: .leading) {
                        CustomTextField(secureInput: false, titleKey: "Email Address", fieldText: self.$user.email).autocapitalization(.none).keyboardType(.emailAddress)
                        if !user.validEmailAddressText.isEmpty {
                            Text(user.validEmailAddressText).font(.caption).foregroundColor(.red)
                        }
                    }
                    VStack(alignment: .leading) {
                        CustomTextField(secureInput: true, titleKey: "Password", fieldText: self.$user.password)
                        if !user.validPasswordText.isEmpty {
                            Text(user.validPasswordText).font(.caption).foregroundColor(.red)
                        }
                    }
                    VStack(alignment: .leading) {
                        CustomTextField(secureInput: true, titleKey: "Confirm Password", fieldText: self.$user.confirmPassword)
                        if !user.passwordsMatch(_confirmPW: user.confirmPassword) {
                            Text(user.validConfirmPasswordText).font(.caption).foregroundColor(.red)
                        }
                    }
                }.frame(width: 300)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                VStack(spacing: 20 ) {
                    FormButton(buttonText: "Sign Up", buttonAction: {
                        // Signup
                        FBAuth.createUser(withEmail: self.user.email,
                                          name: self.user.fullname,
                                          password: self.user.password) { (result) in
                            switch result {
                            case .failure(let error):
                                self.errorString = error.localizedDescription
                                self.showError = true
                            case .success( _):
                                print("Account Creation Successful")
                            }
                        }
                        
                    })
                    .opacity(user.isSignInComplete ? 1 : 0.5)
                    .disabled(!user.isSignInComplete)
                    
                    Spacer()
                }.padding()
            }.padding(.top)
                .alert(isPresented: $showError) {
                    Alert(title: Text("Error Creating an Account"), message: Text(self.errorString), dismissButton: .default(Text("OK")))
                }
                .navigationBarTitle("Sign Up", displayMode: .inline)
                .navigationBarItems(trailing: Button("Dismiss") {
                    self.presentationMode.wrappedValue.dismiss()
                })
        }
    }
}

ForgotPasswordView:

struct ForgotPasswordView: View {
    @State var user: UserViewModel = UserViewModel()
    @Environment(\.presentationMode) var presentationMode
    @State private var showAlert = false
    @State private var errString: String?
    
    var body: some View {
        NavigationView {
            VStack {
                TextField("Enter email address", text: $user.email).autocapitalization(.none).keyboardType(.emailAddress)
                FormButton(buttonText: "Submit", buttonAction: {
                    FBAuth.resetPassword(email: self.user.email) { (result) in
                        switch result {
                        case .failure(let error):
                            self.errString = error.localizedDescription
                        case .success( _):
                            break
                        }
                        self.showAlert = true
                    }
                })
                
                .disabled(!user.isEmailValid(_email: user.email))
                Spacer()
            }.padding(.top)
                .frame(width: 300)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            .navigationBarTitle("Request a password reset", displayMode: .inline)
                .navigationBarItems(trailing: Button("Dismiss") {
                    self.presentationMode.wrappedValue.dismiss()
                })
                .alert(isPresented: $showAlert) {
                    Alert(title: Text("Password Reset"), message: Text(self.errString ?? "Success, Password reset email was sent, Check your email"), dismissButton: .default(Text("OK")) {
                        self.presentationMode.wrappedValue.dismiss()
                    })
                }
        }
    }
}


问题:

在登录视图中,我第一次点击注册按钮时,sheet 打开了 ForgotPasswordView() // 这是错误的

当我关闭 sheet 并点击忘记密码时,sheet 打开忘记密码 // 这是正确的

当我关闭 sheet 并再次点击注册按钮时,sheet 打开 SignUpView // 这是正确的

如何在第一次尝试时打开 SignupView?

我解开了这个谜,在 LoginView :

我改变了这个:

SignInWithEmailView(showSheet: $showSheet, action: $action)

对此:

SignInWithEmailView(showSheet: $showSheet, action: self.action == nil ? $action : $action)

它就像一个魅力 ;)