Password Validation Screen in SwiftUI (1/3)

Bartłomiej Lańczyk
5 min readApr 4, 2023

--

In this article, we will take a look at how to create a simple and clean password setting and confirmation screen with validation. The article is divided into two parts. In the first one, we will focus on the UI part, and in the second one, we will cover the logic of validating our elements.

Introduction

The premise of our example will be very simple. The screen will allow the user to enter a password, which must meet several conditions, such as:

  • minimum of 8 characters
  • minimum one special character
  • minimum one digit
  • minimum one uppercase latter

And a repeated password that should:

  • same as the entered password

Thanks to the well-designed interface, the user can see in real-time what conditions they still need to meet, or whether by improving one of the secure password conditions, they have inadvertently broken another.

Let’s get started

At the very beginning, we create the view and elements that are unique, i.e., appear in singular form on the screen. For elements that we will duplicate or will have similar behavior, we will create separate files so that we do not duplicate the code that we have already written.

struct SignUpPasswordScreen: View {
var body: some View {
VStack(spacing: 0) {
VStack {
VStack(alignment: .leading, spacing: 10) {
Text("Password")
.font(.title)
.bold()
Text("Password must have more than 8 characters, contain some special character, one digit, one uppercase letter")
.font(.caption)
}
Spacer()
Button {

} label: {
Text("Sign Up")
.font(.system(size: 19.5, weight: .medium))

}
.frame(width: 300, height: 50)
.foregroundColor(.white)
.background(.black)
.cornerRadius(6)
}
}
}
}

TextFields

At this stage, we will create an element responsible for entering the password and confirmation by the user. To make our example flexible and possible to expand, we will use an enum type, which will allow us to easily extend it if we decide to add other functionalities of a similar nature, such as username, email, etc. However, it should be bear in mind that password input elements use SecureField, while elements that do not require additional privacy use TextField.

enum UserFormType {
case password, repeatPassword

var title: String {
switch self {
case .password:
return "Password"
case .repeatPassword:
return "Repeat Password"
}
}
}

struct UserFormTextField: View {
@Binding var text: String
var type: UserFormType

var body: some View {
VStack(alignment: .leading) {
SecureField("\(type.title)", text: $text)
.font(.body)
}
.padding()
.frame(maxHeight: 60)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(.gray, lineWidth: 2)
)
}
}

RequirementsPickerView

Next, we will create an element that allows for a visual representation of whether our password meets the conditions. The implementation of this element could be simpler, but we will use our own implementation of ToggleStyle, which will give this element typical Toggle behavior, except for the ability to click. This may be somewhat confusing, but in the subsequent parts of the user authentication tutorial, we will use a clickable Toggle, and thanks to this approach, we will be able to use an already implemented solution.

struct CheckboxToggleStyle: ToggleStyle {
func makeBody(configuration: Configuration) -> some View {
Image(systemName: configuration.isOn ? "checkmark.square.fill" : "square.fill")
.resizable()
.scaledToFit()
.foregroundColor(configuration.isOn ? .blue : .white)
.overlay {
if !configuration.isOn {
RoundedRectangle(cornerRadius: 8)
.stroke(Color.blue, lineWidth: 5)
}
}
.cornerRadius(8)
.onTapGesture {
configuration.isOn.toggle()
}
}
}
enum RequirementsType {
case eightChar, spacialChar, oneDigit, upperCaseChar, confirmation

var description: LocalizedStringKey {
switch self {
case .eightChar:
return "8 characters"
case .spacialChar:
return "One special character"
case .oneDigit:
return "One digit"
case .upperCaseChar:
return "One uppercase letter"
case .confirmation:
return "The password and confirmation must match"
}
}
}

struct RequirementsPickerView: View {
var type: RequirementsType
@Binding var toggleState: Bool

var body: some View {
HStack {
Toggle("", isOn: $toggleState.animation(.easeInOut))
.toggleStyle(CheckboxToggleStyle())
.disabled(true)
.frame(width: 30, height: 30)
Text(type.description)
.font(.headline)
Spacer()
}
}
}

Adding elements to the view

Now we need to add the created components to the view. For now, we only add working states for password, password confirmation and checkboxes, which we will move to a separate ObservableObject in the next section.

struct SignUpPasswordScreen: View {
@State private var password = ""
@State private var confirmPassword = ""
@State private var toggleState = false

var body: some View {
VStack(spacing: 0) {
VStack {
VStack(alignment: .leading, spacing: 10) {
Text("Password")
.font(.title)
.bold()
Text("Password must have more than 8 characters, contain some special character, one digit, one uppercase letter")
.font(.caption)
}
Group {
UserFormTextField(text: $password, type: .password)
VStack(alignment: .leading) {
RequirementsPickerView(type: .eightChar, toggleState: $toggleState)
RequirementsPickerView(type: .spacialChar, toggleState: $toggleState)
RequirementsPickerView(type: .oneDigit, toggleState: $toggleState)
RequirementsPickerView(type: .upperCaseChar, toggleState: $toggleState)
}
UserFormTextField(text: $confirmPassword, type: .repeatPassword)
RequirementsPickerView(type: .confirmation, toggleState: $toggleState)
}.padding(.vertical, 5)
Spacer()
Button {
// sign up action
} label: {
Text("Sign Up")
.font(.system(size: 19.5, weight: .medium))

}
.frame(width: 300, height: 50)
.foregroundColor(.white)
.background(.black)
.cornerRadius(6)
}
.padding()
}
}
}

Hooray! We have managed to create a very nice password setting screen. In the second part of the article, we will focus on the class responsible for listening to changes made by the user and validating the filled fields, which currently do nothing.

Full code is available on Github: https://github.com/miltenkot/EmailAuthenticateScreen

Part 2:

https://medium.com/@miltenkot/how-to-create-a-password-validation-screen-in-swiftui-part-2-bc194b3b81cd

If you enjoyed this article and would like to see more, please leave a reaction.

--

--