Swift Error Handling

I recall reading somewhere about a growing number in the amount of code we write to handle user mistakes. Application users make mistakes and while it sometimes may seem intentional as an attempt to frustrate it is the requirement of developers to protect from them.

We have all heard and joked about this as developers.

Screen Shot 2015-11-07 at 8.49.24 AM

Sometimes I think the proper answer we all need to approach this problem with is looking in the mirror and wondering why we weren’t smart enough to prevent that mistake?

In the following example I am documenting a scenario of validating a users input using some of the new Error Handling features with Swift 2 that will help organize and keep the code cleaner and easier to understand.

While the example is simple hopefully it will give you something to build on for whatever you are working on.

Create Project

Start off with creating a Single View Application:

Screen Shot 2015-10-29 at 6.47.57 PM

Screen Shot 2015-11-07 at 9.02.06 AM

Layout Screen

With the project setup complete click on the projects storyboard (Main.storyboard) and add a Label for the Title, four TextFields that will take input from the user, an error label and finally a button that the user would use to submit their input.

Screen Shot 2015-10-30 at 3.57.27 PM

Once you have added those fields and the constraints go ahead and give it a test run in the simulator.

Screen Shot 2015-10-30 at 3.59.29 PM

The only change that remains with the storyboard is to remove the text on the error label that was added. With the storyboard editor still open click on the Assistant Editor so that both the storyboard and ViewController.swift are displayed.

Screen Shot 2015-01-25 at 3.30.55 PM

Then control drag and create properties for the TextFields and error Label.

    @IBOutlet weak var fieldOneText: UITextField!
    @IBOutlet weak var fieldTwoText: UITextField!
    @IBOutlet weak var fieldThreeText: UITextField!
    @IBOutlet weak var fieldFourText: UITextField!
    
    @IBOutlet weak var errorLabel: UILabel!

You will also want to control drag and create a function for when the user clicks on the button for submitting their entry.

    
    @IBAction func validateFormPressed(sender: AnyObject) {
    }

After that is done you can close the Assistant Editor and you will now begin to work on the code for validating the users input.

Validation Model

Next you will want to add a new file to implement the model that will be used for validating user input.

Screen Shot 2015-10-30 at 4.04.26 PM

The first that will be added are String properties for validating the different entries as well as init method for the construction of the object.

class FormValidationModel {
    var fieldOneText: String?
    var fieldTwoText: String?
    var fieldThreeText: String?
    var fieldFourText: String?
    
    init (fieldOne: String, fieldTwo: String, fieldThree: String, fieldFour: String) {
        self.fieldOneText = fieldOne
        self.fieldTwoText = fieldTwo
        self.fieldThreeText = fieldThree
        self.fieldFourText = fieldFour
    }
}

 Validate Rules

For this example I am going to use some rules for validating user input. The follow are the rules that I am going to be validating against:

  • All of the TextFields have to have something entered in them (no blanks)
  • Field one – Has at least one character.
  • Field two – Has at least two characters.
  • Field three – Has at least three characters.
  • Field four – Has at least four characters.

I probably could have applied some regular expression filters but for this article I felt it was best to give the basic idea and let you take it further.

    func hasEmptyFields () -> Bool {
        var result: Bool = false
        
        if (!fieldOneText!.isEmpty && !fieldTwoText!.isEmpty && !fieldThreeText!.isEmpty && !fieldFourText!.isEmpty) {
            result = true
        }
        
        return result
    }
    
    func validationFieldOne() -> Bool {
        if fieldOneText?.characters.count >= 1 {
            return true
        }
        
        return false
    }
    
    func validationFieldTwo() -> Bool {
        if fieldTwoText?.characters.count >= 2 {
            return true
        }
        
        return false
    }
    
    func validationFieldThree() -> Bool {
        if fieldThreeText?.characters.count >= 3 {
            return true
        }
        
        return false
    }
    
    func validationFieldFour() -> Bool {
        if fieldFourText?.characters.count >= 4 {
            return true
        }
        
        return false
    }

I could have the ViewController call each of those functions and report back an error but that kind of defeats the purpose of the model. Instead the next step is to bundle them all up into a function that will validate the users input and let us know if there are any errors.

    func validateForm() throws -> Bool  {
        return true
    }

When this method is called it will validate the entries and if all is good it will then return true. The problem now however; is how will the ViewController know where the problem is if false is returned?

To handle that lets create an exception to report an error and it will have an error message included that could be displayed to the user.

Create an Exception

Next you will want to again add a new file to implement the exception.

Screen Shot 2015-10-30 at 4.04.26 PM

For error handling in Swift you will want to create an enum that will inherit from the ErrorType protocol. What I am going to cover in this example is very basic error handling and you can find more information here.

Our requirements were simple so lets just create an exception that will represent our different requirements.

enum FormValidationErrors: ErrorType {
    case emptyField
    case FieldOne
    case FieldTwo
    case FieldThree
    case FieldFour
}

Next we’ll create a set of error messages that can be displayed to the user. For this example I am going to modify the enum so that it also implements the CustomStringConvertible protocol which will also allow us to print the exception to an output console using print().

enum FormValidationErrors: ErrorType, CustomStringConvertible {
    case emptyField
    case FieldOne
    case FieldTwo
    case FieldThree
    case FieldFour

    var description: String {
        switch self {
        case .emptyField: return "Empty fields encountered. \n Please complete all of the fields."
        case .FieldOne: return "Field one could not be validated. \n Please enter more than one character."
        case .FieldTwo: return "Field two could not be validated. \n Please enter more than two characters."
        case .FieldThree: return "Field three could not be validated. \n Please enter more than three characters."
        case .FieldFour: return "Field four could not be validated. \n Please enter more than four characters."
        }
    }
}

Form Validation

Next we are going to edit the validateForm() function again and include the checks against the different validation functions that were implemented. In the past you might have implemented the checks with a group of if and else if statements. With the latest in Swift there is now the guard statement which has several features one of which is its ability make the code more readable and maintainable.

In this example I am using the guard statement for improving readability of the code; for more information go you can review the documentation on Apple’s site here.

The basic format of a guard statement is:

    guard control-statement else {
        throw exception
    }

For now whenever the guards control-statement returns false we will throw an exception in the else statement.

    func validateForm() throws -> Bool  {
        guard hasEmptyFields() else {
            throw FormValidationErrors.emptyField
        }
        
        guard validationFieldOne() else {
            throw FormValidationErrors.FieldOne
        }
        
        guard validationFieldTwo() else {
            throw FormValidationErrors.FieldTwo
        }
        
        guard validationFieldThree() else {
            throw FormValidationErrors.FieldThree
        }
        
        guard validationFieldFour() else {
            throw FormValidationErrors.FieldFour
        }
        
        return true
    }

With the exception and model code complete all that remains is implementing the ViewController.swift so that when the function for handling the submit button is pressed it uses it all. Before I do that let me cover the basics of exception handling.

    do {
        try code-statement-with-exception()
        code statements that run if no exception
    } catch let error as CustomErrorType {
        print("handle custom exception ErrorType")
    } catch {
        print("general exception message")
    }

You can now make the changes to the ViewController.swift to use the new exception that was developed. You will want to make the following changes to the validateFormPressed() function.

    @IBAction func validateFormPressed(sender: AnyObject) {
        let validator = FormValidationModel(fieldOne: fieldOneText.text!, fieldTwo: fieldTwoText.text!, fieldThree: fieldThreeText.text!, fieldFour: fieldFourText.text!)
        
        do {
            errorLabel.text = ""
            try validator.validateForm()
        } catch let error as FormValidationErrors {
            print(error)
            errorLabel.text = error.description
        } catch {
            errorLabel.text = "There was an error validating your form entry.\n Please try again."
        }
    }

For now you can the complete source here and as always Happy Coding!!!

Changing gears is fun and challenging

It has been awhile since I have written last and not because I haven’t had anything interesting happening as of late but mostly because I have been in the middle of learning new stuff.

Last year I had started to work with Swift some but like all new languages I have learned I found that was fighting against it. In defense of the language it wasn’t because Swift is hard to learn but rather because I just wasn’t sure of its success in really going mainstream. #gasp

Ok listen I was learning it because I had hopes for it but part of me enjoyed ObjectiveC and I thought to myself why would Apple think it could improve on something already working?

“If it aint broke, don’t fix it” – Bert Lance

Well sometimes changing gears and disrupting your work is a good idea. With that in my thoughts and the release of Swift 2.0 I felt it was time to take my latest adventure in learning serious and change my gears in development.

Well with a new app released and two more in development (all using Swift) I can definitely say I am loving Swift and wondering why Apple didn’t think of this sooner?

So my writing will be resuming again soon but with a different twist on the language in use.

As usual happy coding (in Swift)!!!

Tracking User Touches with UIImageView

Whether you are having a user draw pictures or allowing the drag elements on the screen there are multiple purposes behind being able to track the location of a users touch in your app. I am going to document a quick example that I recently developed for an app that I have developed.

In this example I am documenting how to track a users touch location. Hopefully this example will give you something to build on for whatever you have in mind.

Create Project

Layout Screen Design

Start off with create a Single View Application:

Screen Shot 2015-05-04 at 10.45.09 PM

Screen Shot 2015-05-04 at 10.46.12 PM

Layout Screen

With the project setup complete click on the projects storyboard (Main.storyboard) and add a Image View to the view. You will want to stretch it out so that it uses the entire display is used as well as add Constraints so that control will be sized for whatever device used.

Screen Shot 2015-05-04 at 11.02.49 PM

With the view setup complete the next step is wiring the UIImageView control into a property for the ViewController.

With the storyboard editor still open click on the Assistant Editor so that both the storyboard and ViewController.h are displayed.

Screen Shot 2015-01-25 at 3.30.55 PM

Then control drag and create a property for the UIImageView:

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

After that is done you can close the Assistant Editor and you will now begin to work on the code that will track the user touches.

Tracking Touches

The rest of the work will be handled in the implementation of the ViewController so click on ViewController.m.

First change the interface to include some properties so that you can track the difference between a user moving their finger or just tapping the screen.

@interface ViewController () {
    bool isMoving;
    CGPoint lastTouchLocation;
}

Then in the viewDidLoad method make sure to initialize the isMoving property.

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    isMoving = NO;
}

Touch Events

Now it’s time to add the methods that will called when the user has touched the screen, is moving their finger and when they have stopped touching the screen. For right now just add the following code and then later we’ll come back and fill them each with more code.

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}

For each of the methods we’re going to use the following common set of code that will get adjusted to better match each method:

// get one touch event from the NSSet that was passed.
UITouch *touch = [touches anyObject];
// from the touch event get the x,y coordinates via a CGPoint
CGPoint currentLocation = [touch locationInView:[self imageView]];

For both the touchesBegan and touchesMoved method we are going to want to record the location in the lastTouchLocation property. This will allow us to track not only where the users finger is on the screen but more importantly where it was previously. Also need to set the boolean variable isMoving so that in the touchesEnded method we can determine whether the user tapped the screen or dragged their finger.

Change both the methods to match the following:

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint currentLocation = [touch locationInView:[self imageView]];

    isMoving = NO;
    
    lastTouchLocation = currentLocation;

    NSLog(@"user has started to touch screen %@.", NSStringFromCGPoint(lastTouchLocation));
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    isMoving = YES;
    
    UITouch *touch = [touches anyObject];
    CGPoint currentLocation = [touch locationInView:[self imageView]];

    NSLog(@"user is moving from %@ to %@", NSStringFromCGPoint(lastTouchLocation), NSStringFromCGPoint(currentLocation));
    
    lastTouchLocation = currentLocation;
}

Finally you will want to handle the touchesEnded method with the following code that will be able to determine whether the user just tapped the screen or actually dragged their finger across it.

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    
    UITouch *touch = [touches anyObject];
    CGPoint currentLocation = [touch locationInView:[self imageView]];

    if (YES == isMoving) {
        NSLog(@"user finished moving from  %@ to %@.", NSStringFromCGPoint(lastTouchLocation), NSStringFromCGPoint(currentLocation));
    } else {
        NSLog(@"user just tapped the screen without moving at %@.", NSStringFromCGPoint(lastTouchLocation));
    }
}

Go ahead and run the code in your debugger and as you tap or drag your finger across the screen you should see messages being logged in the debugger.

Screen Shot 2015-05-05 at 9.38.06 PM

As I mentioned earlier whether you are having a user draw pictures or allowing them to drag elements on the screen there are multiple uses to tracking the location of a users touch in your app.

For now you can find the source here and as always Happy Coding!!!