繁体   English   中英

为什么点击提交后文字会消失?

[英]Why does Text disappear when i click submit?

当我在 EditText 视图中输入以填写所有必需的信息,然后单击提交时。 我输入的所有内容都消失了。 我希望保留此文本。 我猜我的@State对象有问题,但无法弄清楚是什么。

注册视图模型

class SignUpViewModel : ObservableObject {

    @Published
    var error: String? = nil

    @Published
    var goHome: Bool = false

    @Published
    var goToLogin: Bool = false

    func onGoToLoginClicked() {
        self.goToLogin = true
    }

    func signUp(firstName: String, lastName: String, email: String, birthday: String, phoneNumber: String, password: String, confirmPassword: String) {
        if (firstName.count < 3) {
            error = "Please enter first name"
            return
        }
        if (lastName.count < 3) {
            error = "Please enter last name"
            return
        }
        if (!email.isEmail()) {
            error = "Pleaes enter valid email"
            return
        }
        if (birthday.isEmpty) {
            error = "Pleae enter valid birthday"
            return
        }
        if (!phoneNumber.isDigits) {
            error = "Please enter valid phone number"
            return
        }
        if (password.count < 8) {
            error = "Please enter a password that is at least 8 characters long"
        }
        if (password != confirmPassword) {
            error = "Password do not match"
        }
        Auth.auth().createUser(withEmail: email, password: password, completion: { authResult, error in
            if authResult != nil {
                self.goHome = true
            } else {
                self.error = error?.localizedDescription
            }
        })
    }
}

注册视图

struct SignUpScreen: View {

    @State
    var firstName: String = ""
    @State
    var lastName: String = ""
    @State
    var birthday: String = ""
    @State
    var number: String = ""
    @State
    var email: String = ""
    @State
    var password: String = ""
    @State
    var confirmPassword: String = ""

    @EnvironmentObject
    var viewModel: SignUpViewModel


    var body: some View {
        ZStack {
            VStack {
                VClearBackground()
                Spacer()
            }
            ScrollView {
                VStack(alignment: .leading) {
                    Group {
                        PreHeaderText(header: "Get Started")
                            .alignmentGuide(.leading, computeValue: { d in
                                d[.leading]
                            })
                            .padding(EdgeInsets.init(top: 32, leading: 0, bottom: 0, trailing: 0))
                        HeaderText(header: "Create Account")
                        EditText(hint: "Huey", text: $firstName, label: "FIRST NAME", textContentType: UITextContentType.name)
                        EditText(hint: "Freeman", text: $lastName, label: "LAST NAME", textContentType: UITextContentType.name)
                        EditText(hint: "04-19-1994", text: $birthday, label: "BIRTHDAY")
                        EditText(hint: "(281) 456-7890)", text: $number, label: "MOBILE NUMBER", textContentType: UITextContentType.telephoneNumber, keyboardType: UIKeyboardType.phonePad)
                        EditText(hint: "email@exmaple.com", text: $email, label: "EMAIL", textContentType: UITextContentType.emailAddress)
                        EditText(hint: "********", text: $password, label: "PASSWORD", textContentType: UITextContentType.newPassword)
                        EditText(hint: "********", text: $confirmPassword, label: "CONFIRM PASSWORD", textContentType: UITextContentType.newPassword)
                    }
                    Group {
                        if self.viewModel.error != nil {
                            HStack {
                                Spacer()
                                Text(viewModel.error ?? "")
                                    .foregroundColor(ColorTheme.error.color)
                                Spacer()
                            }
                            .padding()
                        }
                        HStack {
                            Spacer()
                            VowerButton(text: "Submit") {
                                self.viewModel.signUp(firstName: self.firstName, lastName: self.lastName, email: self.email, birthday: self.birthday, phoneNumber: self.number, password: self.password, confirmPassword: self.confirmPassword)
                            }
                            Spacer()
                        }
                        .padding()

                        HStack {
                            Spacer()
                            NavigationLink(destination: LoginScreen(), isActive: $viewModel.goToLogin) {
                                CtaText(text: "Have an account?", cta: "Login") {
                                    self.viewModel.onGoToLoginClicked()
                                }
                            }
                            .padding()
                            Spacer()
                        }

                        Spacer()
                    }
                }
            }
            .padding(EdgeInsets.init(top: 16, leading: 16, bottom: 16, trailing: 16))
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
        }
        .background(LinearGradient(gradient: Gradient(colors: [.black, ColorTheme.brandPurple.color]), startPoint: .top, endPoint: .bottom))
        .edgesIgnoringSafeArea(.all)
    }
}

编辑文本视图

struct EditText: View {

    var hint: String
    @Binding
    var text: String
    var label: String = ""
    var defaultValue =  ""
    var textContentType: UITextContentType? = .none
    var keyboardType: UIKeyboardType = .default

    private func initializeDefaultValue() {
        DispatchQueue.main.async {
            self.text = self.defaultValue
        }
    }

    var body: some View {
        initializeDefaultValue()
        return VStack(alignment: .leading) {
            Text(label).font(.system(size: 12)).bold()
                .foregroundColor(ColorTheme.text.color)
            HStack {
                TextField(hint, text: $text)
                .lineLimit(1)
                .textContentType(textContentType)
                .keyboardType(keyboardType)
                    .foregroundColor(ColorTheme.text.color)
            }
            Divider().background(Color(ColorTheme.brandBlue.value))
        }
        .padding(EdgeInsets.init(top: 12, leading: 0, bottom: 8, trailing: 0))
    }
}

预览

问题代码在SignUpScreen

@ObservedObject
var viewModel: SignUpViewModel = SignUpViewModel()

每当重新评估视图时, SignUpViewModel创建一个新的SignUpViewModel

您可以在视图之外创建视图模型,并将其直接传递给构造函数,或者使用environmentObject()将其注入environmentObject()

要改用环境对象,请将上述声明更改为:

@EnvironmentObject
var viewModel: SignUpViewModel

然后像这样创建你的视图:

var signUpViewModel = SignUpViewModel()

// ...

SignUpScreen()
    .environmentObject(signUpViewModel)

问题出在您的EditText视图中。

struct EditText: View {

    var hint: String
    @Binding
    var text: String
    var label: String = ""
    var defaultValue =  ""
    var textContentType: UITextContentType? = .none
    var keyboardType: UIKeyboardType = .default

    private func initializeDefaultValue() {
        DispatchQueue.main.async {
            self.text = self.defaultValue
        }
    }

    var body: some View {
        initializeDefaultValue()
        return VStack(alignment: .leading) {
            Text(label).font(.system(size: 12)).bold()
                .foregroundColor(ColorTheme.text.color)
            HStack {
                TextField(hint, text: $text)
                .lineLimit(1)
                .textContentType(textContentType)
                .keyboardType(keyboardType)
                    .foregroundColor(ColorTheme.text.color)
            }
            Divider().background(Color(ColorTheme.brandBlue.value))
        }
        .padding(EdgeInsets.init(top: 12, leading: 0, bottom: 8, trailing: 0))
    }
}

具体来说,它在body属性中。 这是一个计算属性,每当重新计算视图时,SwiftUI 都会获取它。 在这种情况下,当SignUpScreen视图的error属性更改时会发生这种情况,因为所有子视图都被重新计算。

重新计算此EditText视图时,将调用initializeDefaultValue()函数(它是body属性中的第一行)。 这将清除文本字段。

至于解决方案,我不确定为什么您实际上完全需要initializeDefaultValue函数。 它似乎最适合 ViewModel 或其他一些位置。


另外,我看到的其他一些东西:

func signUp(firstName: String, lastName: String, email: String, birthday: String, phoneNumber: String, password: String, confirmPassword: String) {
    if (firstName.count < 3) {
        error = "Please enter first name"
        return
    }
    if (lastName.count < 3) {
        error = "Please enter last name"
        return
    }
    if (!email.isEmail()) {
        error = "Pleaes enter valid email"
        return
    }
    if (birthday.isEmpty) {
        error = "Pleae enter valid birthday"
        return
    }
    if (!phoneNumber.isDigits) {
        error = "Please enter valid phone number"
        return
    }
    if (password.count < 8) {
        error = "Please enter a password that is at least 8 characters long"
    }
    if (password != confirmPassword) {
        error = "Password do not match"
    }
    Auth.auth().createUser(withEmail: email, password: password, completion: { authResult, error in
        if authResult != nil {
            self.goHome = true
        } else {
            self.error = error?.localizedDescription
        }
    })
}

除了最后两个错误,这个函数在所有错误情况下都会提前返回——我认为这是一个错误。

if self.viewModel.error != nil {
    HStack {
        Spacer()
        Text(viewModel.error ?? "")
        .foregroundColor(ColorTheme.error.color)
        Spacer()
    }
    .padding()
}

SignUpScreen视图的这一部分应该能够简化为:

if let err = self.viewModel.error {
    HStack {
        Spacer()
        Text(err)
        .foregroundColor(ColorTheme.error.color)
        Spacer()
    }
    .padding()
}

或者,如果在这种情况下不允许使用 if-let 语句:

if self.viewModel.error != nil {
    HStack {
        Spacer()
        Text(viewModel.error!)
        .foregroundColor(ColorTheme.error.color)
        Spacer()
    }
    .padding()
}

如您所知,错误是非nil


希望所有这些都有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM