Protocols and Delegates and Swift, oh My!

Many years ago when I was learning Objective-C my initial impression of protocols and delegates was one of confusion. When I first started reading and learning about them and their idea I was expecting something hard to totally comprehend and most likely difficult to implement.

Very shortly however I began to realize that it was neither.

Protocols

I think that Apple gives a great description for a protocol.

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.

A more simple example (non programming) of protocols is the process of building a house.

You start first with the creation of a set of architectural drawings that are printed (blueprints) and distributed to the various contractors whose responsibility is to create an implementation. Think of protocols as the architects printed blueprints and the implementation of them as the actual house being constructed.

Back to the programming world, and for those that are new to Swift, think of protocols as abstract interfaces which allow you define an interface to be used in the construction of an object.

Delegates

The process of delegation allows you (the delegator) to notify another object or hand over work to another object (the delegate) which has an interest in your execution. In my opinion you will see it used most often as a form of notification from one object to another.

For the MVC purists that are out there you will most likely be familiar to delegates as the Observer Pattern that glues everything together.

Putting it All Together

In the sample application I am going to demonstrate how you can use a protocol to implement functions used for the purposes of notification as well as how to use them to get information from the delegate.

In the application there will be a button that when clicked runs an asynchronous function which will repeat a unit of work based on a counter. To create some delay and simulate that each unit of work is actually doing something I added a sleep call for one second.

While the asynchronous function is running I want it to do the following:

  • Notify when work has started
  • Ask the delegate how many units of work it should execute
  • Notify when work has completed
  • Optionally I would like for it to update me as each unit of work is complete.

Let’s get started.

Create Project

Start off with creating a Single View Application:

Screen Shot 2015-10-29 at 6.47.57 PM

Screen Shot 2016-02-23 at 4.12.45 PM

Layout Screen

With the project setup complete click on the projects storyboard (Main.storyboard) and add a Label for a status that will get displayed and a button labeled Run Work.

Screen Shot 2016-03-02 at 5.36.51 PM

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

Screen Shot 2016-03-02 at 5.41.22 PM

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

Screen Shot 2015-02-26 at 11.00.34 PM

Then control drag and create a property for the Label as well as a function to handle Run Work button when it is clicked.

    @IBOutlet weak var labelWorkStatus: UILabel!

    @IBAction func runWork(sender: AnyObject) {
    }

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

Create the Protocol

Next you will want to add a new file for the protocol.

Screen Shot 2015-10-30 at 4.04.26 PM

A basic protocol would be defined as follows:

protocol ProtoExample {
    // add your definitions here
}

Here is the code that you will want to paste for the protocol that will be implemented. There are be a couple of parts to this that are different from the normal that I will explain.

@objc protocol ProtoExample {
    var workTime : UInt32 { get }
    
    func workIsStarting()
    func workIsComplete()
    
    optional func workInProgress()
}

Protocol definitions are fairly straightforward when you look at them. You basically define the layout of the function that you expect to be implemented much like you would in any other class. The exception of course is that you don’t supply an implementation.

When dealing with properties you have to make sure that you define them with a var in the front and then follow them with their access method (get set). If you wanted to create a property with a get and set access it would look like the following:

    var workTime : UInt32 { get set }

What about that @objc that I added to the front of the protocol definition?

In the requirements I discussed the option of getting notifications as the work progresses. In order to achieve this I marked the workInProgress function as optional meaning that the implementor of the protocol would not be required to implement this. In order to make use of this keyword you have to also mark your protocol with @objc.

Adding this attribute doesn’t require you to now use Objective-C in your development. The only downside that comes from marking the protocol this way is that it means only class objects can inherit from your protocol.

You can get more information about the @objc attribute here.

Create the Model

Next you will want to create the model which will implement the asynchronous function as well as use the delegate the protocol was designed for.

Screen Shot 2015-10-30 at 4.04.26 PM

The requirements for the model are simple so lets just create an asynchronous function that makes use of the protocol. I am not going to go into the details of queues and asynchronous programming but for those that want more information you can read a great article about asynchronous operations for iOS here.

class ProtoModel {
    var delegate : ProtoExample?
    
    func doSomeProcessing() {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
            // let them know that we are starting
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.delegate?.workIsStarting()
            })
        
            // do some stuff
            var workTime : UInt32 = 0
            if let del = self.delegate {
                workTime = del.workTime
            }
            
            while 0 < workTime { sleep(1) dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    self.delegate?.workInProgress?()
                })

                workTime--
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.delegate?.workIsComplete()
            })
        })
    }
}

In this example the delegate is not mandatory for execution. I did this intentionally to demonstrate how the delegate would be used in the common scenarios where users may not be interested in the notifications.

If you wanted to make the delegate a requirement then you would change the code to look more like the following:

class ProtoModel {
    var delegate : ProtoExample
    
    init (delegate: ProtoExample) {
        self.delegate = delegate
    }
    
    func doSomeProcessing() {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
            // let them know that we are starting
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.delegate.workIsStarting()
            })
        
            // do some stuff
            var workTime = self.delegate.workTime
            
            while 0 < workTime { sleep(1) dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    self.delegate.workInProgress?()
                })

                workTime--
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.delegate.workIsComplete()
            })
        })
    }
}

A couple of simple things to notice is that the property is no longer marked as optional and with that comes the requirement of the init constructor. Also notice how the calls using the delegate have changed.

But wait the signature to the workInProgress still has the optional tag. This is because if you recall the function was flagged with the optional keyword.

Implementing the Protocol

To implement the protocol open the ViewController.swift and make the required changes so that it inherits from and implements the protocol.

In this example you can make note that the optional function we defined is not being used. This is allowed because of the optional attribute we assigned to the function.

class ViewController: UIViewController, ProtoExample {
    
    @IBOutlet weak var labelWorkStatus: UILabel!
    
    // implement the protocol
    var workTime : UInt32 { return 10 }

    func workIsComplete() {
        labelWorkStatus.text = "Work is Complete"
    }
    
    func workIsStarting() {
        labelWorkStatus.text = "Work is Starting"
    }

Add the model as an optional property and make sure that it is created in the viewDidLoad function.

    var protoModel : ProtoModel?

    override func viewDidLoad() {
        super.viewDidLoad()

        // create and setup the model
        self.protoModel = ProtoModel()
        self.protoModel?.delegate = self
        
        // setup the view
        labelWorkStatus.text = "Ready for Work"
    }

Finally change the handler for when the button gets clicked so that it will call the asynchronous function doSomeProcessing created in the model.

    @IBAction func runWork(sender: AnyObject) {
        if let model = self.protoModel {
            labelWorkStatus.text = "Work is requested"
            model.doSomeProcessing()
        }
    }

With all that complete go ahead and run the application, click the button and you should see the status being updated as the function doSomeProcessing progresses.

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

Struggling… step back, take a different approach

I started a few weeks ago to write another post about working with RESTful services but I kept running into roadblocks.

Frustrating because the roadblocks weren’t on how to implement everything but rather on how to explain the different facets of implementation. For anyone who has actually followed my posts you hopefully know by now that I try to keep them short and simple (as much as possible).

I still think that writing an example for working with RESTful services can be simple. I just need to cover some of the other basics like Protocols and maybe even the use of NSNotificationCenter as an alternative.

It has taken me a couple of weeks to come to this decision but it’s nice to have some closure. I have been so irritated by the block that I have at times just refused work on it (even more frustrating).

So plan now is to work on supporting articles and then come back at the RESTful approach with those as support.

As always Happy Coding!!!

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!!!