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.
Last night, I released Lab Tick 0.9.3 which fixes a number of small bugs. The biggest change in this release is support for fast user switching. In previous versions of Lab Tick, you either had to disable or quite Lab Tick before you would switch to a different account on your notebook - otherwise, Lab Tick would continue to run and try to control the illumination. This caused erratic behaviour when another instance of Lab Tick was running under a different account.
Also, since Xcode 3.2 in Snow Leopard comes with a static analyzer built-in, I could find a number of small memory leaks, which should hopefully reduce memory usage by a bit.
However, even though Lab Tick 0.9.3 runs perfectly fine on Snow Leopard, it won't run in 64 bit. That is because some of the APIs I use to control the backlit keyboard are not fully 64-bit-capable and have been deprecated by Apple. I will look into replacing those APIs with modern ones that have 64 bit support. Since spare time is always an issue, I cannot make any promises on a release date.
Until then, I hope the lack of support for 64 bit doesn't bother you too much.