Lately, I have been using a lot of REST APIs for various projects that I have been working on. One development pattern that I have constantly used among all these projects is that of using various NSOperation objects, feed them to an NSOperationQueue and get the results fed back to the caller via delegation.
Why Would You Do This?
Now, why would you go through the trouble of learning all these APIs, creating a delegate protocol and implementing all this stuff if you could use a simple initWithContentsOfURL: (or similar)? The main reason here is asynchronous networking. If you're going to just fetch network data, such as strings, images or whole XML documents from remote servers, you are going to see some latency, especially if you're developing for the iPhone and running on an EDGE or 3G network.
If you were to use synchronous networking from within your main thread, you would be blocking your application's UI until your method stack returns and the system can redraw your views. If you're looking at multiple seconds of latency, which might easily occur if you're fetching dynamically generated data from a server, this practically makes your application unusable. The solution to this problem is to push networking tasks into separate functions and move those to different threads.
Of course, you could just detach new thread selectors all over your controller, but that would be rather ugly, error-prone and a bitch to maintain. Fortunately, Apple introduced NSOperation and NSOperationQueue a while back (in Mac OS X 10.5 Leopard).
For your projects, you will create a subclass of NSOperation and override the -main method to do your bidding. This is where the heavy lifting should take place and all your network latency will not matter anymore. I have written a sample application that uses an NSOperation subclass to fetch an image via HTTP and return it to the controller using a delegate protocol that I have written specifically for this task. My -main method look like this:
This method does nothing more than what you would previously have done to retrieve an image given a URL (_url and _delegate are instance variables that were filled during initialization). The delegate implements the selectors defined in my protocol, errorOccurred: and didReceiveImage:.
So much for the heavy lifting. But how do you actually get this method to run in the first place? This is easy, thanks to NSOperationQueue, which provides a method to queue NSOperation subclasses for execution. In my application controller's -awakeFromNib method, I instantiate my NSOperation subclass and add it to the NSOperationQueue like this:
Add the implementation of the delegate protocol and you're done! What you end up with is a nice, clean and efficient way of dealing with networking that helps to keep your code readable, error-free and makes for a better user experience by keeping the main thread free of blocking operations.