Category Archives: Opinion

Streaming

Here’s how streaming works. In general. This is not news and is not really helpful. I’ll post it anyway.

There are three main tasks when you’re streaming. Could be audio, could be video, it doesn’t really matter. First, you’ll pull the content from the network. Buffering. Then you’ll decode the content. Then you’ll render it. (Yes, the output of audio is rendering it to the output buffer)

Many applications express these three job systems by using multiple threads. It’s a wise choice and makes a lot of sense. The problems appear when the specifics of the implementation come in to play. What happens when a network connection fails half way through? You’ve spun up three threads, one provides the other with raw data, one decodes the data, and one outputs the data as audio. How do you handle a stall?

Now, how do you handle a decoding error? It’s totally possible your source has promised a MIME type that it doesn’t conform to. Promised MP3 but given an M4A? With audio, it’s often close enough.

Once you start? That’s the easy bit. Stopping is hard. Three threads working away delivering data asynchronously? You need to coordinate them all stopping immediately. Without just shutting down the app. That may sound like a piece of cake but it’s really a pie in the face.

The concept is dead simple. One thread downloads the data and then passes it off to the decoding thread. The decoding thread turns MP3 or whatever format into the native PCM format that can be output by the device. The device takes that input and queues it onto a native audio output channel.

Sounds easy, right?

– Guy

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.