Skip Navigation LinksHome > View Post

iOS, blocks and HTTP requests

For some time now I’ve been occasionally dipping my toes into iOS development. The problem is, the large gaps between my visitations mean that I almost completely forget everything I learn about Objective C inbetween visits. One of the key reasons I created this blog was for me to create notes for myself as reference and hopefully they’ll be useful to others. This is definitely one of those posts.

Every time I work with Objective C, I have to remind myself how to author and work with blocks – mostly because I really hate working with delegates and protocols when coding in Objective C.

In a sentence, blocks are (ahem) blocks of code that can be passed around like any other variable or object. If you’re a C# or JavaScript developer this idea will be vary familiar to you. Some examples:

C# and Lambdas

// signature accepting a 'block' (Func<string, string> is a 
//function that accepts a string and returns a string)
public void DoFooAndThenCallBar(Func<string, string> bar); // calling that method with a ‘callback’ bar instance.DoFooAndThenCallBar(name => { return "Hello " + name + ", this is from the 'block'"; });

JavaScript

// signature accepting a function
function doFooAndThenCallBar(bar)

// calling the method with a callback 'bar'
instance.doFooAndThenCallBar(function(name) {
    return "Hello " +  name + ", this is from the 'block'";
});


To me (maybe due to exposure over the years) the C# and JavaScript approaches are very obvious and very intuitive. I can’t say the same for Objective C.

However, I love using blocks/anonymous delegates/lambdas/functions when using continuation passing style asynchronous programming and recently I was making HTTP requests from iOS and wanted to use this approach. The daddy class for this kind of thing in iOS is NSMutableURLRequest and NSURLConnection. Unfortunately, NSURLConnection uses delegates (not blocks) so I wanted to write a little adapter to make this easy.

First, let’s take a look at the equivalent Objective C block for our examples above:

Objective C

-(void) doFooAndThenCallBar:(NSString*(^) (NSString* response)) 
callback { callback(@"Josh"); }

[instance doFooAndThenCallBar:^(NSString* response) { return [NSString stringWithFormat(
@"Hello %@, this from the 'block'"]; }];

That’s pretty easy. Another example worth posting (because again, to me, it’s completely counter-intuitive) is how you create a variable so you can store the block for use later:

NSString* (^ callbackBlock)(NSString *response);

// 10 points to anybody who guessed that the variable is called
// 'callbackBlock'
it can be invoked: callbackBlock(@"Josh");

And to close, this is the rough outline of what my block wrapper for HTTP requests looked like. Notice that the class is not thread safe and shouldn’t be used for multiple requests. But you can easily create a new instance for each request (yes, I was using ARC). The implementation here is stupidly simple and shows a callback that simply hands you the request body as a string.

I’ll leave it as an exercise to the reader to complete the request wrapper that fulfills their needs (including better error handling).

JoshRequest.h

#import <Foundation/Foundation.h>

@interface JoshRequest : NSObject<NSURLConnectionDelegate> { @private NSMutableData* _receivedData; void (^ callbackBlock)(NSString *response); }

-(JoshRequest*) init; -(void) postToUrl: (NSString*) url withBody: (NSData*) body
withCallback: (void(^) (NSString* response)) callback;

@end

JoshRequest.m

#import "JoshRequest.h"

@implementation JoshRequest

- (JoshRequest*) init { return self; }

-(void) postToUrl:(NSString *)url withBody:(NSData *)body
withCallback: (void (^)(NSString *))callback { NSMutableURLRequest* request = [NSMutableURLRequest
requestWithURL: [NSURL URLWithString:url]]; [request setHTTPMethod:@"POST"]; NSError *error; // should check for and handle errors here [request setHTTPBody:body]; NSURLConnection *conn = [[NSURLConnection alloc]
initWithRequest: request delegate:self]; _receivedData = [NSMutableData data]; callbackBlock = callback; } #pragma NSUrlConnectionDelegate Methods

-(void)connection:(NSConnection*)conn didReceiveResponse:
(NSURLResponse *)response { if (_receivedData == NULL) { _receivedData = [[NSMutableData alloc] init]; } [_receivedData setLength:0]; }

- (void)connection:(NSURLConnection *)connection didReceiveData:
(NSData *)data { // Append the new data to receivedData. [_receivedData appendData:data]; }

- (void)connection:(NSURLConnection *)connection didFailWithError:
(NSError *)error { //Naive error handling - log it! NSLog(@"Connection failed! Error - %@ %@", [error localizedDescription], [[error userInfo] objectForKey:
NSURLErrorFailingURLStringErrorKey]); }

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSString *txt = [[NSString alloc] initWithData:_receivedData
encoding: NSASCIIStringEncoding]; callbackBlock(txt); }

@end

Huge thanks to Chris Risner for his help with this.

 
Josh Post By Josh Twist
4:57 AM
04 Jun 2012

» Next Post: Introducing Windows Azure Mobile Services
« Previous Post: Project Liike

Comments are closed for this post.

Posted by Aviel Lazar @ 06 Jun 2012 7:45 AM
Indeed your approach is correct. More and more wrappers are written everyday turning the delegate patterns to blocks. However in this case I would just go and use the AFNetworking library( has blocks). It comes with a json parser as well and it still pretty lightweight.

© 2005 - 2014 Josh Twist - All Rights Reserved.