NSURLConnection Helper

Jeff has got a good post up on the importance of using the iPhone’s built-in asynchronous communication classes and methods in lieu of threads:

Don’t spawn threads for asynchronous communications unless you would have used threads in the same situation if there was no network code.

Jeff argues for this position on the basis of overhead. I would make another argument: threading is too hard to get right to be worth the trouble most of the time. (I say this as someone who likes writing multithreaded code.) The difficultly of getting multithread code right is exponential in its complexity, and software has a way of always turning out a bit more complex than you might have expected.

Today I want to present a little helper class for NSURLConnection. If you’re going to use this class asynchronously, you’re going to need to supply a delegate, and it can be a minor nuisance to come up with one when you start working with this class. The MyNSURLConnectionDelegate class presented below should get you started.

Concept

The MyNSURLConnectionDelegate class is intended to provide a simple, immediately usable delegate implementation for asynchronous NSURLConnections. It would be used something like this:

The only slightly weird thing about MyNSURLConnectionDelegate is that it retains its target; this is unusual, but done to reflect the fact that NSURLConnection is itself weird in retaining its delegate (until it’s finished loading).

The context object is intended to wrap user-defined data; it has no meaning to MyNSURLConnectionDelegate.

This class doesn’t reference NSURLConnectionDelegate because the latter entity is declared as a category on NSObject (instead of as, for example, a protocol). I declare and define all relevant methods (per the documentation) in this class even though, for most of them, the implementation is minimal.

I don’t declare or define the connection:needNewBodyStream: method, which isn’t well documented, and mentioned only in one obscure corner of the Foundation Constants Reference.

There isn’t much to see here; I define some convenience accessors in an extension, and, as I mentioned above, retain the target object.

Now, let’s move on to the actual delegate methods. Many of them are designed to mimic the behavior you’d get from an NSURLConnection if its delegate didn’t implement the relevant method at all, and all of them perform some logging, which is intended to aid in development.

This class contains no logic to handle authentication, so we instruct the underlying sender to continue without credentials. (If we implement this method but take no action on receipt of an authentication challenge, the NSURLConnection will hang forever.)

On receipt of data, append it to responseData. (I assume that at least one connection:didReceiveResponse: message is guaranteed to be sent before any connection:didReceiveData: messages; this interpretation of the contract may not be valid. If it’s wrong, responseData may be nil, and data handled by this method may be dropped on the floor. Caveat coder.)