Form Validation in Swift

Login to Access Code

Login to access video

If you’re building or designing an app, chances are you’re going to build a form. If you want someone to make an account, provide feedback, or (hopefully) pay you something, you can’t avoid forms. Despite their ubiquity, I can’t think of anyone who likes filling out forms, especially on a phone. At the same time, I can’t think of a single back-end engineer who likes weeding through bad input data because users can’t be bothered to enter a valid phone number, for example. Therefore, front-end validation is an essential part of creating good U/X and saving yourself a bit of work on the back-end. This post and screencast are going to cover a quick data validation method using a handy library called “swift-validator”.

Create A New Project

First off let’s create a new Xcode project and title it “Forming” or whatever you like. Select single page app and set the language to Swift. I’d set the device to iPhone as well, but that’s not crucial.

Screenshot of Xcode: Create Project

Screenshot of Xcode: Name Project

Now that we have our project, let’s make our layout simple by going to the project navigator and selecting the top-level Forming project to reveal the general app settings. We want to go to the Deployment Info section and deselect Landscape Left and Landscape Right under “Device Orientation”. Then, in the Main Interface dropdown, we want to select Main.storyboard. This ensures we have a storyboard to work with to create our layout and that we only have to worry about supporting portrait view.

Xcode Screenshot of Orientation Settings

Create the form layout

Now let’s hop over to our Main.storyboard file to create our form we need for this tutorial. You will see a blank view in the interface. The grey arrow next to the view indicates this is the initial view when the user opens the app, so we simply need to add our input form to this view. Before anything else, let’s make our lives easier by restricting the size of our view to a 4-inch iPhone. To do this, select the ViewController from the left-hand navigator in the storyboard view, then use the dropdown in the Size field of the attributes inspector (on the right-hand side) to select “iPhone 4-inch”.

Screenshot of Xcode Setting Size to iPhone 4-inch

To begin building our form, drag a Label object and a text field from the object library onto our view.

Screenshot of Xcode: Adding a label to View Controller

Double click on the label you’ve just added to the view to edit the text to say “Email”. Also, make your text field a bit wider to accommodate an email address. Next, duplicate the label and text field by selecting both and going to Edit > Duplicate. Drag the duplicates so they are left-aligned with the originals and rename the duplicate label “Phone Number”. Select both labels and both input fields and center align them with the view by dragging towards the center until the handy center-align guide appears.

App running in simulator with form fields

Finally let’s drag a button from the object library on the view and center align it below the phone number field. Double click on the button and edit the title to read “Submit.” This will be our button that submits the form for validation.

App running in simulator with submit button added

Now is a good time to build and run your project to make sure the view loads properly.

Adding swift-validator Library

The last bit of setup before we start coding is adding the validator library. Start by cloning the swift-validator library. Once you have the repo on your computer, drag the whole folder into your project.

Screenshot showing library being dragged into project

All we really care about is the lib folder inside the validator.xcodeproj file inside the Swift-Validator folder so you can actually extract that folder and delete everything else.

Looking at the library folder in the project

To make sure the swift-validator library copied over correctly, go to your ViewController.swift file and define a variable as an instance of the Validator class.

let validator = Validator();

If you don’t any reference errors, we are in business!

Referencing our input fields in code

Now that we’ve drawn our layout and added the swift-validator library, we are going to need to reference our fields in our code in order to validate down the road. In order to do that, open both the Main.storyboard and ViewController.swift files. Control-click on the input field under the Email label and drag the line that gets created into the ViewController.swift. An input field will appear, enter emailTextField. This defines a variable that refers to our input field. Do the same for the second input field and call that phoneTextField.

Making IBOutlet connection in Xcode

Now let’s set those new fields to a delegate of the parent class. Your ViewController.swift file should look like this:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate 
{ 
  let validator = Validator()

  @IBOutlet weak var emailTextInput: UITextField!
  @IBOutlet weak var phoneTextInput: UITextField!

  override func viewDidLoad() 
  {
    super.viewDidLoad()

    emailTextInput.delegate = self
    phoneTextInput.delegate = self
  }

  override func didReceiveMemoryWarning() 
  {
    super.didReceiveMemoryWarning()
  }
}

Setting up the fields we want to validate

Now we jump into our validation code. First, let’s create an array of the fields we are going to validate:

let Fields =  ["Email", "Phone"]

Next inside viewDidLoad we need to register our fields with the Validator class. We calling registerFieldByKey on the instance of Validator and pass it our outlet and validation rules:

validator.registerFieldByKey(
  Fields[0], 
  textField: emailTextInput, 
  rules: [.Required, .Email]
)

validator.registerFieldByKey(
  Fields[1], 
  textField: phoneTextInput, 
  rules: [.Required, .PhoneNumber]
)

Let’s analyze our code:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate 
{ 
  @IBOutlet weak var emailTextInput: UITextField!
  @IBOutlet weak var phoneTextInput: UITextField!

  let Fields = ["Email", "Phone"]
  let validator = Validator()

  override func viewDidLoad() 
  {
    super.viewDidLoad()

    emailTextInput.delegate = self
    phoneTextInput.delegate = self

    validator.registerFieldByKey(
      Fields[0], 
      textField: emailTextInput, 
      rules: [.Required, .Email]
    )

    validator.registerFieldByKey(
      Fields[1], 
      textField: phoneTextInput, 
      rules: [.Required, .PhoneNumber]
    )
  }

  override func didReceiveMemoryWarning() 
  {
    super.didReceiveMemoryWarning()
  }
}
  • The ViewController class conforms to the UITextField delegate, to allow our text field object to communicate to the validator when an event has happened
  • We connect both the emailTextInput and phoneTextInput fields from our Storyboard to our ViewController
  • We set the emailTextInput and phoneTextInput delegates to self since the parent class has the appropriate UITextFieldDelegate
  • We create an array of keys that will correspond to the fields we want to validate and use the registerFieldByKey method of the Validator class, which takes a key, textField, and a rules array
  • The emailTextInput rules object needs to conform to the rules for valid email entry
  • The phoneTextInput needs to conform to the rules for a valid 10-digit phone number
  • Both fields should be required before the user can submit the form

Validating the form

To validate the fields we have registered, we need our ViewController to conform to the ValidationFieldDelegate protocol:

class ViewController: UIViewController, UITextFieldDelegate, ValidationFieldDelegate

The protocol requires the conforming class to contain the validationFieldFailed(key:String, error:ValidationError) and validationFieldSuccess(key:String, validField:UITextField) functions. For now, let’s set the textField background color of the field to green or red to signal a passing or failing validation:

func validationFieldFailed(key:String, error:ValidationError) 
{
  //set error text field to red
  error.textField.backgroundColor = UIColor.redColor()
}
func validationFieldSuccess(key:String, validField:UITextField) 
{
  //set valid text field to green
  validField.backgroundColor = UIColor.greenColor()
}

We now simply need to add a method that gets called when the form is submitted that calls the validateFieldByKey method of the Validator class. We want this to run when the user presses the submit button so we define an IBAction that we will tie to our submit button in our storyboard:

@IBAction func submitTapped(sender: AnyObject) 
{
  validator.validateFieldByKey(Fields[0], delegate:self)
  validator.validateFieldByKey(Fields[1], delegate:self)
}

To tie the action to the submit button, go to Main.storyboard and control click the submit button and drag an outlet from the touchUpInside event to the @IBAction in ViewController.swift

connecting an action in Xcode

Build and run. Fill out the form and submit and you’ll see the validation is working properly!

Application running in simulator with validations

Make our UX better

Ok our form validates, but we want to make our user’s lives easier by providing immediate feedback to the user as soon as he/she finishes editing a form field. We will add a validateField method to our class to do so. We will then call this method when the user finishes editing an input field.

@IBAction func validateField(sender: AnyObject) 
{
  switch (sender as UITextField) 
  {
    case emailTextInput :
      validator.validateFieldByKey((Fields[0]), delegate: self)
      println("Validating email...", sender)
    case phoneTextInput :
      validator.validateFieldByKey((Fields[1]), delegate: self)
      println("Validating phone...", sender)
    default :
      println("no fields to validate")
  }
}

The validateField method employs a switch statement that compares the sender (i.e. the field that calls the method) to our defined field variables. If there is a match, the validateFieldByKey method for that field gets called. Now we simply tie the our input fields in our storyboard to our IBAction for the editing did finish event.

Connecting the fields to the custom action

Now build and run and notice how our validation happens as soon as you finish editing an input field. Much better!

Now that we’ve covered the basics, go on to explore the details of swift-validator to make custom validations and take your forms to the next level. Swift-validator makes it so easy to provide visual feedback on input validity that you have no excuse for poor form design. While I can’t stress enough how important form U/X is, it’s only a piece of the puzzle in designing a good app.

For more great UI and UX screencasts check out Making iOS Apps Sexy and Creating an Animated Tab Bar Navigation.