Mobile Development

Delegates (Protocols)

Delegates provide a messaging system between two separate objects. We use delegates to inform controller classes of some updated information or request that an action is to take place.

Delegation is a design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type. [1]

The above diagram (sourced from [1] below) shows an example of a delegate call between a window and its controller. The window is asking if it's OK to close and the controller refuses. Thus, the window stay active.

Let's check out an example of a practical use case for delegates.

Example

So I have a toddler. And part of that experience is teaching my son how to count. We really want to push the limits of counting and go all the way to twenty. Now how would we represent this within a object oriented program? I want to know when my son has started counting, what number he has counted to and when he is finished. Let's see how we can do it with delegates.

import Foundation

protocol CountingDelegate {
    func didBeginCounting()
    func didCount(currentValue:Int)
    func didEndCounting(finalCount: Int)
}

class CountTo {

    var delegate: CountingDelegate?

    func beginCounting(countUntil: Int) {
        var internalCounter = 0

        // OK, we're about to begin counting, let's inform our delegate
        delegate?.didBeginCounting()

        while ++internalCounter < countUntil {
            delegate?.didCount(internalCounter)
        }

        // Look's like we completed our while loop, let's inform our delegate
        delegate?.didEndCounting(internalCounter)
    }
}

class LearningToddler: CountingDelegate {
    var name: String
    var age: Int
    let maximumCountingAbility = 20
    let countingActivity = CountTo()

    init(toddlerName: String, toddlerAge: Int) {
        name = toddlerName
        age = toddlerAge
    }

    func beginCounting() {
        countingActivity.delegate = self
        countingActivity.beginCounting(maximumCountingAbility)
    }

    // Define our delegate methods which will be invoked
    func didBeginCounting() {
        NSLog("We have begun counting!")
    }

    func didCount(currentValue: Int) {
        NSLog("Our current count is \(currentValue) and we're counting until \(maximumCountingAbility)")
    }

    func didEndCounting(finalCount: Int) {
        NSLog("We successfully counted all the way to \(finalCount)!")
    }
}

// Running the example
let toddler = LearningToddler(toddlerName: "Raleigh", toddlerAge: 2)
toddler.beginCounting()

Copying the above code into Playgrounds should yield the following result:

2015-01-04 14:47:35.685 MyPlayground[21014:3462547] We have begun counting!
2015-01-04 14:47:35.686 MyPlayground[21014:3462547] Our current count is 1 and we're counting until 20
2015-01-04 14:47:35.687 MyPlayground[21014:3462547] Our current count is 2 and we're counting until 20
2015-01-04 14:47:35.689 MyPlayground[21014:3462547] Our current count is 3 and we're counting until 20
2015-01-04 14:47:35.690 MyPlayground[21014:3462547] Our current count is 4 and we're counting until 20
2015-01-04 14:47:35.692 MyPlayground[21014:3462547] Our current count is 5 and we're counting until 20
2015-01-04 14:47:35.694 MyPlayground[21014:3462547] Our current count is 6 and we're counting until 20
2015-01-04 14:47:35.695 MyPlayground[21014:3462547] Our current count is 7 and we're counting until 20
2015-01-04 14:47:35.697 MyPlayground[21014:3462547] Our current count is 8 and we're counting until 20
2015-01-04 14:47:35.699 MyPlayground[21014:3462547] Our current count is 9 and we're counting until 20
2015-01-04 14:47:35.701 MyPlayground[21014:3462547] Our current count is 10 and we're counting until 20
2015-01-04 14:47:35.703 MyPlayground[21014:3462547] Our current count is 11 and we're counting until 20
2015-01-04 14:47:35.704 MyPlayground[21014:3462547] Our current count is 12 and we're counting until 20
2015-01-04 14:47:35.706 MyPlayground[21014:3462547] Our current count is 13 and we're counting until 20
2015-01-04 14:47:35.708 MyPlayground[21014:3462547] Our current count is 14 and we're counting until 20
2015-01-04 14:47:35.709 MyPlayground[21014:3462547] Our current count is 15 and we're counting until 20
2015-01-04 14:47:35.711 MyPlayground[21014:3462547] Our current count is 16 and we're counting until 20
2015-01-04 14:47:35.712 MyPlayground[21014:3462547] Our current count is 17 and we're counting until 20
2015-01-04 14:47:35.714 MyPlayground[21014:3462547] Our current count is 18 and we're counting until 20
2015-01-04 14:47:35.716 MyPlayground[21014:3462547] Our current count is 19 and we're counting until 20
2015-01-04 14:47:35.717 MyPlayground[21014:3462547] We successfully counted all the way to 20!

Let's explore delegates conceptually next.

[Video] Protocols and Delegates

Below is a video which will provide more context on both the concepts and another example use case for delegates: iOS Swift Basics Tutorial: Protocols and Delegates

https://www.youtube.com/watch?v=9LHDsSWc680

References

[1] Swift Programming Guide - https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

[2] Cocoa Core - Delegation https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.htmls