Complex Password Validation in SwiftUI
Hello, I have built a complex password validation in SwiftUI. This is just for learning and practicing but I thought it worth sharing here as you can modify this according to your needs by only changing the regex.
So for this validation tool, I considered these:
- Password length must be 8 characters or more.
- Must contain at least 1 lowercase letter.
- Must contain at least 1 uppercase letter.
- One numeric digit at least.
- At least one special character.
So I will just make a simple password field (SecureField) and then I will add a button to validate the password.
When the user enters the password and clicks on validate it will show what kind of validation error occurred.
Password validator in SwiftUI
Let’s first create the validation system without showing the exact validation error(s). But it will make the button green if password is validated perfectly.
import SwiftUI struct ContentView: View { @State private var password = "" @State private var passwordIsValid = false @State private var errorMessage = "" var body: some View { Form { Section(header: Text("Password")) { SecureField("Enter your password", text: $password) .textContentType(.password) } Section { Button("Validate Password") { validatePassword() } .foregroundColor(.white) .frame(maxWidth: .infinity) .padding() .background(passwordIsValid ? Color.green : Color.gray) .cornerRadius(10) } if !passwordIsValid && !errorMessage.isEmpty { Section(header: Text("Validation Error")) { Text(errorMessage) .foregroundColor(.red) .multilineTextAlignment(.center) } } } .navigationBarTitle("Password Validation") } private func validatePassword() { let passwordPattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$" let passwordPredicate = NSPredicate(format: "SELF MATCHES %@", passwordPattern) if !passwordPredicate.evaluate(with: password) { errorMessage = "Password must be at least 8 characters long and include at least 1 lowercase letter, 1 uppercase letter, 1 numeric digit, and 1 special character." } else { errorMessage = "" passwordIsValid = true } } }
The main regex part is ^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$
Show specific reason: password validation error in SwiftUI
Now I am going to make some changes to my code. I will show the exact reasons for the validation error as Text.
import SwiftUI struct ContentView: View { @State private var password = "" @State private var passwordIsValid = false @State private var errorMessages: [String] = [] var body: some View { Form { Section(header: Text("Password")) { SecureField("Enter your password", text: $password) .textContentType(.password) } Section { Button("Validate Password") { validatePassword() } .foregroundColor(.white) .frame(maxWidth: .infinity) .padding() .background(passwordIsValid ? Color.green : Color.gray) .cornerRadius(10) } if !passwordIsValid && !errorMessages.isEmpty { Section(header: Text("Validation Errors")) { ForEach(errorMessages, id: \.self) { errorMessage in Text(errorMessage) .foregroundColor(.red) .multilineTextAlignment(.center) } } } } .navigationBarTitle("Password Validation") } private func validatePassword() { var errors: [String] = [] if password.count < 8 { errors.append("Password must be at least 8 characters long.") } if !password.contains(where: { $0.isLowercase }) { errors.append("Password must include at least 1 lowercase letter.") } if !password.contains(where: { $0.isUppercase }) { errors.append("Password must include at least 1 uppercase letter.") } if !password.contains(where: { $0.isNumber }) { errors.append("Password must include at least 1 numeric digit.") } if !password.contains(where: { "!@#$%^&*()_-+=[{]};:'\",<.>/?".contains($0) }) { errors.append("Password must include at least 1 special character.") } errorMessages = errors passwordIsValid = errors.isEmpty } }
Output:
By seeing the output you must be thinking that you are actually unable to see what I am typing in the box. So I will modify my code again and show how to add the show password option to it.
I have also created a whole SwiftUI login form with show-hide password option. You can check it: Login Form in SwiftUI
Password validation with show – hide option in SwiftUI
I have added this button:
Button(action: { showPassword.toggle() }) { Image(systemName: showPassword ? "eye.slash.fill" : "eye.fill") .foregroundColor(.gray) }
The final full code will be like this:
import SwiftUI struct ContentView: View { @State private var password = "" @State private var passwordIsValid = false @State private var errorMessages: [String] = [] @State private var showPassword = false var body: some View { Form { Section(header: Text("Password")) { HStack { if showPassword { TextField("Enter your password", text: $password) .textContentType(.password) } else { SecureField("Enter your password", text: $password) .textContentType(.password) } Button(action: { showPassword.toggle() }) { Image(systemName: showPassword ? "eye.slash.fill" : "eye.fill") .foregroundColor(.gray) } } } Section { Button("Validate Password") { validatePassword() } .foregroundColor(.white) .frame(maxWidth: .infinity) .padding() .background(passwordIsValid ? Color.green : Color.gray) .cornerRadius(10) } if !passwordIsValid && !errorMessages.isEmpty { Section(header: Text("Validation Errors")) { ForEach(errorMessages, id: \.self) { errorMessage in Text(errorMessage) .foregroundColor(.red) .multilineTextAlignment(.center) } } } } .navigationBarTitle("Password Validation") } private func validatePassword() { var errors: [String] = [] if password.count < 8 { errors.append("Password must be at least 8 characters long.") } if !password.contains(where: { $0.isLowercase }) { errors.append("Password must include at least 1 lowercase letter.") } if !password.contains(where: { $0.isUppercase }) { errors.append("Password must include at least 1 uppercase letter.") } if !password.contains(where: { $0.isNumber }) { errors.append("Password must include at least 1 numeric digit.") } if !password.contains(where: { "!@#$%^&*()_-+=[{]};:'\",<.>/?".contains($0) }) { errors.append("Password must include at least 1 special character.") } errorMessages = errors passwordIsValid = errors.isEmpty } }
Output:
Leave a Reply