[英]Why does Text disappear when i click submit?
When I type in my EditText view to fill out all the required information and then click submit.当我在 EditText 视图中输入以填写所有必需的信息,然后单击提交时。 Everything I typed disappears.
我输入的所有内容都消失了。 I want this text to remain.
我希望保留此文本。 I am guessing there is something wrong with my
@State
objects but cannot figure out what.我猜我的
@State
对象有问题,但无法弄清楚是什么。
SignUpViewModel注册视图模型
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
}
})
}
}
SignUp View注册视图
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)
}
}
EditText View编辑文本视图
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))
}
}
The problem code is in SignUpScreen
:问题代码在
SignUpScreen
:
@ObservedObject
var viewModel: SignUpViewModel = SignUpViewModel()
Whenever the view is re-evaluated, a new SignUpViewModel
is created.每当重新评估视图时,
SignUpViewModel
创建一个新的SignUpViewModel
。
You can create the view model outside the view, and either pass it to the directly to the constructor, or inject it to the environment using environmentObject()
.您可以在视图之外创建视图模型,并将其直接传递给构造函数,或者使用
environmentObject()
将其注入environmentObject()
。
To use an environment object instead, change the above declaration to:要改用环境对象,请将上述声明更改为:
@EnvironmentObject
var viewModel: SignUpViewModel
And then create your view like this:然后像这样创建你的视图:
var signUpViewModel = SignUpViewModel()
// ...
SignUpScreen()
.environmentObject(signUpViewModel)
The problem is in your EditText
view.问题出在您的
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))
}
}
Specifically, it's in the body
property.具体来说,它在
body
属性中。 This is a computed property that is fetched by SwiftUI whenever the view is recomputed.这是一个计算属性,每当重新计算视图时,SwiftUI 都会获取它。 In this case, this happens when the
error
property of the SignUpScreen
view changes, as all the subviews are recomputed.在这种情况下,当
SignUpScreen
视图的error
属性更改时会发生这种情况,因为所有子视图都被重新计算。
When this EditText
view is recomputed, the initializeDefaultValue()
function is called (it's the first line in the body
property).重新计算此
EditText
视图时,将调用initializeDefaultValue()
函数(它是body
属性中的第一行)。 This clears the text fields.这将清除文本字段。
As for a solution, I'm not sure why you actually need the initializeDefaultValue
function in here at all.至于解决方案,我不确定为什么您实际上完全需要
initializeDefaultValue
函数。 It seems best suited for the ViewModel or some other location.它似乎最适合 ViewModel 或其他一些位置。
Also, just some other things that I saw:另外,我看到的其他一些东西:
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
}
})
}
This function returns early in all error cases except the last two — I believe this was a mistake.除了最后两个错误,这个函数在所有错误情况下都会提前返回——我认为这是一个错误。
if self.viewModel.error != nil {
HStack {
Spacer()
Text(viewModel.error ?? "")
.foregroundColor(ColorTheme.error.color)
Spacer()
}
.padding()
}
This part of the SignUpScreen
view should be able to be simplified to this: SignUpScreen
视图的这一部分应该能够简化为:
if let err = self.viewModel.error {
HStack {
Spacer()
Text(err)
.foregroundColor(ColorTheme.error.color)
Spacer()
}
.padding()
}
or, if if-let statements are not allowed in this case:或者,如果在这种情况下不允许使用 if-let 语句:
if self.viewModel.error != nil {
HStack {
Spacer()
Text(viewModel.error!)
.foregroundColor(ColorTheme.error.color)
Spacer()
}
.padding()
}
as you know that the error is non- nil
.如您所知,错误是非
nil
。
Hope all of this helps!希望所有这些都有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.