Online Book Reader

Home Category

Cocoa Programming for Mac OS X - Aaron Hillegass [114]

By Root 819 0
settings. As you solve problems in your own projects, you may find blocks to be a great fit in some unexpected places.

RanchForecast: Going Asynchronous


Our RanchForecast application works great in ideal circumstances. That is, with a speedy Internet connection. However, what if our Internet connection is poor? Or what if we were loading a much larger XML document that might take several seconds (or worse) to download?

Our customers will complain, and rightly so, that the application looks as if it has frozen until the request completes and the table updates. The reason is that we are running a synchronous request in the main thread, the very same thread that handles UI events. If we use NSURLConnection in the asynchronous style, however, we can avoid blocking the main thread, and the UI will be nice and responsive. Let’s update our ScheduleFetcher class to do things the Right Way.

Recall that using NSURLConnection asynchronously means that we will create the connection and specify a delegate, using initWithRequest:delegate:. This call will return immediately, and the delegate will be called to handle various events during the connection’s lifetime. NSURLConnection works with the run loop to make this possible.

In our application, ScheduleFetcher will act as the connection’s delegate and implement the three delegate methods needed to handle receiving data and the successful and unsuccessful completion of the request:

- (void)connection:(NSURLConnection *)connection

didReceiveData:(NSData *)data;

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

- (void)connection:(NSURLConnection *)connection

didFailWithError:(NSError *)error;

Receiving the Asynchronous Response


If the response loading is taking place asynchronously and ScheduleFetcher will not block, how will RanchForecastAppDelegate know when the class schedule has been loaded or when an error has occurred?

We can accomplish this in several ways. The most obvious approach would be to add a pointer to RanchForecastAppDelegate in the ScheduleFetcher. Once the schedule has been fetched, the fetcher would call a method on the app delegate (updateWithClasses:, perhaps). The downside of this approach, however, is that we would have just made ScheduleFetcher dependent on RanchForecastAppDelegate. If we wanted to use ScheduleFetcher in another project later on (and we will), we would need to edit its code, which then leaves us with multiple versions of ScheduleFetcher.

Another approach is to use the delegate pattern. It works great for NSURLConnection; ScheduleFetcher could use it as well. We would define a ScheduleFetcherDelegate protocol, and RanchForecastAppDelegate would conform to the protocol and set itself as the delegate. This approach is very reasonable; it decouples the classes, keeping ScheduleFetcher reusable, but it feels somewhat heavy-handed for such a simple Web service response.

Yet another approach is to use our knowledge of blocks to apply the completion block design pattern. In this pattern, our fetch method on ScheduleFetcher would take a block as its only parameter. ScheduleFetcher then calls the block later when it is ready to deliver the results or report an error. Completion blocks are very compact; no additional methods are needed and they have the advantage of allowing us to keep the response-handling code close to the place where the Web service call is initiated.

Let’s modify ScheduleFetcher to perform the request asynchronously and report the results using a completion block.

In ScheduleFetcher.h, define the ScheduleFetchResultBlock type. Because the block syntax involves a good bit of punctuation, it is often helpful to typedef block types so that they can be used more gracefully in the future.

#import

typedef void (^ScheduleFetcherResultBlock)(NSArray *classes,

NSError *error);

Now add three new instance variables and the replacement for fetchClassesWithError: to ScheduleFetcher:

@interface ScheduleFetcher : NSObject

Return Main Page Previous Page Next Page

®Online Book Reader