02 January 2016

Delegation is probably not easy to grasp for most. It certainly wasn’t for me. I want to change that by putting it in a way that can be understood by my readers and students. Of all things, delegation is one of the most characteristic patterns found throughout iOS and OS X development. I’d argue that it is one of the cornerstones of apps for the Apple ecosystem. It’s a rather perfect mechanism for updating the UI after background operations.

It can even serve to facilitate UI updates for alternate paradigms such as MVVM. See MVVM in Swift with ReactiveCocoa 4.

Delegate or not?

A delegate is someone that performs actions on the behalf of another. If I delegate work to you, the work will be performed by you on my behalf, if you agree. In software terms, our agreement is outlined in a protocol. When you conform to my protocol, that is sufficient for you to be accepted as my delegate.

Reasoning about delegates

Getting going with delegation can be achieved by answering a few key questions.

  • Who is the delegate?
  • Where to place the protocol?
  • Where to implement the delegate methods?

Who is the delegate?

This is the same as asking “Who needs to do something?” or “Who needs to perform the action?”

The answer is, whoever is performing the action will be the delegate.

Once you know who the delegate is, it’s easier to determine where to place the delegate protocol and where to create the delegate property.

The delegate protocol, in general, lives with the delegate property since it is someone else who will be the delegate. It is the other class that is going to conform to the protocol.

Where to place the protocol?

Place the protocol with the delegate property. The protocol goes with the property. For a more memorable form, that can be boiled down to protocol-with-property.

protocol ADelegate: class {
    func firstDelegateMethod() 
    func secondDelegateMethod() 
}

class AClass {
    weak var delegate: ADelegate?	
}

Where to implement the delegate methods?

Implement the methods where the action is, where the work needs to be done. That’s a delegate = self situation. That’s easy to remember because that’s one of the most common delegate assignments in iOS and OS X programming.

Self can only be a delegate when it conforms to the proper protocol. The protocol lives somewhere else. The protocol is the list of functions that the delegate needs to implement. If you are implementing delegate methods in the class that contains the protocol, then you have probably confused upside with down, an easy mistake to make after going through the delegation spin cycle. 😜

class SomeOtherClass: ImaDelegate {
    init() {
        let anObject = AClass()
        anObject.delegate = self
    }

    // MARK: ImaDelegate Methods
    
    func firstDelegateMethod() {
    }

    // and so on...
}

We use weak properties in Swift for class delegates to prevent retain cycles from occurring.

Delegate protocols

Does a delegate ever exist without a protocol? In general, no.

A delegate has a type that matches the protocol for the delegate.

To test your understanding, answer what is the difference between a delegate and a protocol?

Protocol naming

OtherViewControllerDelegate is a rather generic name though perfectly appropriate.

OtherViewControllerDataUpdating or OtherViewControllerDataUpdatable would be much more specific and readily identifiable as being something than an ordinary class.

When to use delegation

Anything event-based can benefit from delegation such as making UI updates after asynchronous operations.

A converse example is that delegation would equally apply to responding to a UI event such as a button press. The view containing the button that receives the event can than delegate actions to another class that contains the code needed to handle the event. Because of delegation, a separation of responsibilities can be maintained (this is what MVC is about).

Conclusion

Using delegation is vital to giving your app the abilities it needs to create an effective user experience.

It’s a slightly more formal approach to handling an event than by other means such as by observation or using a callback due to requiring a protocol.

However, protocols confer the benefit of compile-time checking and serve as an additional source of documentation when named appropriately.



blog comments powered by Disqus