You're an iOS developer. How would you set up a class to notify another object of an event?

In the context of iOS development, a few options may come to mind when answering this question: NotificationCenter, blocks/closures, or delegation. By far, the most popular answer I've received in interviews is delegation, which is understandable given the frequent use of the delegate pattern in iOS APIs. However, there is a difference between notification and delegation, just as the names imply.

Two Obvious Differences

When asking why you might prefer notifications or delegates, a common observation is that notifications can be sent to multiple targets, but delegation only allows for a single target. So if an object is using a delegate protocol as a means of notification, it can only have one object listening for those "notifications". Posting notifications through NotificationCenter allows for multiple listeners.

Someone who has a little more experience might also recognize that NotificationCenter provides loose coupling between the object that sends the notification and the object that responds to it. Neither object needs to know anything about the other. With delegation, there is often tighter coupling between the class that receives the delegate and the implementation of the delegate protocol.

Something Deeper

However, these observations actually point to conceptual differences between notification and delegation. It can be a bit misleading to think of delegation as a means of sending notifications between two objects. Rather, delegation should be thought of as a means for implementing functionality that an object leaves undefined. One object is delegating certain responsibilities to another object, which allows the object to become more flexible and general-purpose. The Apple documentation expresses it this way:

Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object.

Consider UITableView and its delegate, UITableViewDelegate. Every table view must be able to create and configure the cells it displays. However, it's not possible for UITableView to know how to create and configure custom table view cells. Therefore, UITableView delegates that responsibility to another object through UITableViewDelegate.

Using delegation allows you to compose complex objects from simpler objects. In the UITableView example, we are composing a complete table view implementation from an instance of UITableView and object instances that implement UITableViewDelegate. In theory you can swap out distinct implementations of UITableViewDelegate and/or UITableViewDataSource. In such a scenario, it should become clear that delegation is not used for notification but for rounding out functionality that isn't known to the delegating object. The object and the delegate work together as a cohesive unit, each necessarily complementing the other.

Alternate Approaches

In some respects, delegation provides functionality similar to inheritance in object-oriented class heirarchies. A base class may define abstract methods that are implemented in derived classes. The distinction becomes one of using composition (via delegates) versus inheritance (via class heirarchies). One of the benefits of using composition is that delegate implementations can be used with other objects that use the same delegate interface and delegate implementations can be swapped out without needing to recreate derived class instances.

    emailTableView.dataSource = personalAccountDataSource
    emailTableView.delegate = detailedCellDelegate

    emailTableView.dataSource = businessAccountDataSource
    emailTableView.delegate = summaryCellDelegate

In this snippet of code, we can see the possibility of completely rebuilding a table view by simply switching its data source and delegate implementations.

A Source of Confusion

One of the reasons we might confuse delegation with notification is that iOS delegates often have a "notification feel" to them. For instance, the table view delegate defines the following methods:

    func tableView(UITableView, willSelectRowAt: IndexPath)
      // Tells the delegate that a specified row is about to be selected.

    func tableView(UITableView, didSelectRowAt: IndexPath)
      // Tells the delegate that the specified row is now selected.

    func tableView(UITableView, willDeselectRowAt: IndexPath)
      // Tells the delegate that a specified row is about to be deselected.

    func tableView(UITableView, didDeselectRowAt: IndexPath)
      // Tells the delegate that the specified row is now deselected.

Because these methods are called in response to user interaction with the table view, they seem to be notifications that are triggered by a user-initiated event.

The Nature of Notifications

How can we draw a distinction between delegation and notification if the line between them can become so fuzzy? Here's another comment from the Apple documentation:

These recipients of the notification, known as observers, can adjust their own appearance, behavior, and state in response to the event.

There's an interesting choice of phrasing there - "[they] can adjust their own appearance, behavior, and state." When we implement a notification observer, it responds to events by altering itself. When we implement a delegate, it responds to events by altering the appearance, behavior, and state of its associated object.

Summary

Okay. Delegates aren't notifiers. But do I really care? Maybe not. If you know how to do what you want to do, perhaps it doesn't really matter. However, when we're building applications with other engineers, it can become important to communicate in a way that is clear to both parties. If I say we should implement a notification for an event, I'm not suggesting a new delegate method. Similarly, if you suggest adding a delegate, you're envisioning two tightly coupled objects that are working together.

So here are a few ideas you can keep in mind regarding common distinctions:

DelegationNotification
Tightly coupled objectsLoosely coupled objects
Single delegateMultiple observers
Alters sender's behavior and stateAlters the receiver's behavior and state

During my early experience with iOS, I was frustrated by some common uses of delegation and really wanted one-to-many notifications. However, understanding the intention behind delegation (it's completing functionality, not sending a notification) has gone a long way to improving my understanding when building iOS apps.

Further Reading

Delegation
Notification
Delegation pattern
Observer pattern