The Responder Chain: Bubbling Events using NSResponder and UIResponder in Swift

The responder chain is one of those parts of macOS and iOS development that may seem a little strange if you have not done any GUI programming before. Briefly, a responder chain is a hierarichy of objects that can respond to events. So, for example, a click or a tap might be passed up the responder chain until something responds to the action.

But, the responder chain is more than just UI events. We can pass our own custom events up the responder chain as well!

Objective-C

Under Objective-C this was pretty straightforward. Because Objective-C is based around the concept of passing messages (this is derived from Smalltalk, by the way) rather than calling methods, this is pretty easy. You might check to see if a responder responds to a specific message, or proceed up the chain. Something like this:

while(responder != nil) {
    if ([responder respondsToSelector:selector]) {
        [responder performSelector:selector withObject:sender];
        break;
    }
    responder = responder.nextResponder;
}

Swift

Under Swift, things are a little bit different. Swift is much more traditional when it comes to methods and typing, and the predominent approach is to use Protocols to confirm adherence rather than testing for whether an object has a specific method. But this is where things get really fun.

In Swift, you can use an extension on NSResponder or UIResponder in combination with generic types. This allows us to do something like this:

public extension NSResponder {
    public func next<T>() -> T? {
        guard let responder = self.nextResponder() else {
            return nil
        }

        return (responder as? T) ?? responder.next()
    }
}

(For the iOS version, change NSResponder to UIResponder).

Now, declare a protocol that your final target will adhere to. This is equivalent to respondsToSelector in Objective-C.

protocol DoesSomething {
    public func doSomething()
}

Now, when you’re ready to bubble your custom event, it’s a simple one-liner! This is because most controllers, views and many objects descend from NSResponder\UIResponder. You just call next() and test for adherence to your protocol.

func clickHandler() {
    (next() as DoesSomething?)?.doSomething()
}

You can even use this method to find a specific ancestor in the responder chain by testing next() with the specific class name. You can also continue to bubble the event up the responder chain (like if you have multiple classes in the heirarchy that need to respond to the event) by calling next() again in your implementation of doSomething().

Hat tip to this now archived blog post with this fabulous approach in it.

Did something I wrote help you out?

That's great! I don't earn any money from this site - I run no ads, sell no products and participate in no affiliate programs. I do this solely because it's fun; I enjoy writing and sharing what I learn.

All the same, if you found this article helpful and want to show your appreciation, here's my Amazon.com wishlist.

Read More

Hierarchies: Finding Parents, Children and Descendents using Swift

It usually doesn’t take beginning macOS/iOS developers long to discover NotificationCenter and see it as the solution to every single problem of passing data around to different controllers. And NotificationCenter is great, but it has some downsides. Notably, it is very easy to introduce retain cycles (and memory leaks) unless you are very careful to track and free the listener when the object is released. This has bitten me on several occasions. In general, excessive use of NotificationCenter ends up creating a difficult to maintain app where it is not entirely clear what is responding to what and where.

Creating Traits or Mixins in Swift

Object oriented programming is great, but sometimes things don’t fit neatly into a superclass/subclass hierarchy. You may have a piece of code that would be needed in several contexts, but for technical reasons beyond your control you cannot merge them into a single hierarchy. Some languages have the concept of multiple inheritence, where a subclass can specifically inherit from several parents. But this has it’s own set of problems. Many other languages, however, solve this through the use of traits or mixins. These allow us to have a set of methods that are basically copied into the object at compile time. This way they can be used anywhere they are needed. Swift doesn’t have the concept of mixins or traits per se. But, starting with Swift 3, you can get very equivalent functionality using protocol default implementations.