When I type in my EditText view to fill out all the required information and then click submit. 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.
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
:
@ObservedObject
var viewModel: SignUpViewModel = SignUpViewModel()
Whenever the view is re-evaluated, a new SignUpViewModel
is created.
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()
.
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.
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. This is a computed property that is fetched by SwiftUI whenever the view is recomputed. In this case, this happens when the error
property of the SignUpScreen
view changes, as all the subviews are recomputed.
When this EditText
view is recomputed, the initializeDefaultValue()
function is called (it's the first line in the body
property). This clears the text fields.
As for a solution, I'm not sure why you actually need the initializeDefaultValue
function in here at all. It seems best suited for the ViewModel or some other location.
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:
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 self.viewModel.error != nil {
HStack {
Spacer()
Text(viewModel.error!)
.foregroundColor(ColorTheme.error.color)
Spacer()
}
.padding()
}
as you know that the error is non- nil
.
Hope all of this helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.