Response to a Response to my Responder Chain Rant

Ian McCullough has a good post up that was sparked by my half serious and half intentionally silly rant about how best to use the iOS responder chain. I think he mischaracterizes my position but that is through no fault of his own. I didn’t make an argument, I just wanted to blow off a little steam after having spent far too long getting something to work as it should. The problem I encountered exhibits itself in of the most professional, well documented and consistent codebases I’ve worked in. I’ve worked in a lot. I want to be clear — the problem isn’t someone being a goof, it’s that the way this stuff all fits together on iOS is problematic and often opaque.

I’m an Interface Builder advocate. In many ways IB is what sold me on Cocoa in the first place. The fact that it didn’t auto-generate code was simply incredible. The precise problem I encountered was that a button in a table view cell subclass was sending an action message to the First Responder.

In the vast majority of cases a button sending an action up the responder chain is amazing and a true boon of the way AppKit and UIKit work. It becomes problematic when the button is a child view of a table view cell. The receiver of the action cannot know which particular cell invoked the action. Since the odds are if you’re responding to an action from a list of items you’re very likely going to want to know which one of them to act upon.

There are solutions. If your view controller is the one who catches the action sent to the First Responder then it has all of the information it will need to work out which model item needs to be acted upon. But if the action goes any higher up the responder chain then subsequent responders simply don’t have the context they need to do the right thing. They can’t decode which item is being interacted with because they don’t have the table view to hand, or possibly even the data source, to figure it out. These situations are rare but they do happen.

Ian seems to think I advocate a delegate approach. I don’t. It can work and is suited to when you need far more information to be passed than a simple action message can provide but, by and large, that’s not what I’d recommend.

I’m a fan of the responder chain. It’s been a terrific idea for a long time. In the places where it doesn’t work we can figure out how to use it better. In this case, of a button sending an action message to First Responder, from a custom UITableViewCell subclass I’d change things up a little. First, the actions of the buttons in the table cell would target the UITableViewCell subclass I had. When the table view cell was asked to perform an action it could simply pass it up the responder chain with itself as the sender. With the simple convention of an -(id)representedObject method (or Protocol if you want to be fancy) we can at least glean from the sender which item to act upon. This has the benefits of leveraging the responder chain as it was designed to be (and what it’s great at doing) while providing operational context for the action method that will eventually be invoked.

Effectively, this turns the UITableViewCell subclass into a micro-controller object. In practice this is both convenient and honest. The action is not coming from some button. It’s coming from the table view cell asking you to perform some action on the data it represents. You would be shocked if something like UISearchBar fired off action messages up the responder chain and the sender was something like the little cancel button on the right hand side. Could you figure out what the intention was? If you had the view hierarchy, yeah, probably. But it’d be goofy.

The responder chain in both UIKit and AppKit is a very good thing. Leverage it as best you can. Just beware of the limitations.

iOS Table View Cells & The Responder Chain

[open star field]

One may be tempted, when created a custom table view cell, to wire up the action of various buttons it contains to the First Responder. This is a horrible idea. Please, don’t do that.

The rational behind this is that the First Responder

… [and break] …

… [cut to a calm Carl Sagan against the Cliffs of Dover] …

The responder chain works by finding the “first responder” along a chain of objects that have opted in to this system. They can be views or controllers on iOS. The limit of the message passed along this chain is that it has exactly one parameter — the sender.

… [cut to an irritated Joe Pesci leaning against a bar] …

So, you see, as you get higher up the responder chain the less context the responder has to act on. Doing this requires an understanding of the context. If I find a UIButton tossing some message up the responder chain, documented nowhere else except in the Interface Builder UI? That sucks. Do you think I’m being funny? You’re chuckling! Yeah. It’s funny. Very funny.

… [cut to the Death Star Throne Room] …

Without the context of an action one can never satisfy the request. Simply sending a message up the responder chain that some sub-item of a view has been tapped doesn’t help make the user’s intention clear except under the most superficial or specifically co-ordinated conditions.

For each step up that chain there is an expectation of implementation that has been overly abstracted by the idea that one can simply toss this decision someplace else. Sometimes that can work. Eventually it falls apart.

Action verbs are cheap. Context is key.

PUNCH! I dare you. PUNCH! You’ve got no idea what or where to punch but, hell! PUNCH!

… [cut to the edge of the Death Star Throne Room Pitfall Railing] …

See how I set up the context?

PUSH.

Context, then action. Action without context is meaningless.

On Opinionated Software

In the Apple development community the term, “opinionated software” comes up often. It is applied to the design decisions we make while building our apps. Having an opinion and a direction is a good thing — it hones the final result to speak with one voice and be a whole unto itself.

At A&D Chris, Thomas and I are really dedicated to that idea. Napkin is a very opinionated app. Before Chris and Thomas came aboard I had one colour and it was hard to convince me otherwise. (It was the green you see in the toolbars) The case of Napkin is illustrative, not narrative. We’re all bathing in caviar and Champaign I can’t pronounce. (It’s not recommended. Between the bubbles, sugar and little caviar things it’s not comfortable.) That said, being opinionated isn’t the goal. Being useful is.

Being opinionated and shipping the truest form of your vision of software doesn’t assure success. I understand the amount of heart, soul, concentration and perseverance it takes to ship a piece of software that really makes you proud and hits all of the marks you’d set for yourself and your team. It can be a really great piece of software.

That doesn’t mean it deserves to be a hit.

More accurately it doesn’t mean you should expect it to be a hit. Hits are hard. Really hard. I’ve had a couple. And, to be honest if I’d had to pick … not the ones I’d have swung for.

This recent discussion of being able to make a living on the App Store has made me think about this a lot more. No, your odds of making a living on the App Store aren’t great. There was a gold rush. Some people made money. It’s more or less over now.

I do believe that if you continue to do good work, communicate with customers and partners well, then there’s a viable business to be in.

I’ve got 1015 unread emails so I’ll call this a post.