Tag Archives: programming

Block Delegates

Often I find myself implementing the same delegate protocol over and over. Consider, for example, the Facebook SDK for iOS. I’d like to make lots of requests to the Graph API, and not have a single callback method

request:didLoad:

in a single class that looks like:

-(void)request:(FBRequest*)request didLoad:(id)result
{
    if (request == mainRequest)
    {
        // handle result
    }
    else if (request == subRequest1)
    {
        // handle result
    }
    else if (request == anotherRequest)
    {
        // handle result
    }
    //... far too many if blocks for my liking
}

This happens because we use one class as the delegate for all the requests. The alternative is to implement multiple classes, but then the handling code becomes spread across, well, multiple classes, which is yucky.

So what to do? Well (this has probably been done before but) my solution is to implement a delegate class once, and for each request, instantiate one, and pass it implementations using block properties. I will call this pattern Block Delegates. It goes like this.

First, set up a skeleton delegate, which implements the delegate protocol and has block properties for each delegate method that might be called:

@interface FBRequestBlockDelegate : NSObject <FBRequestDelegate> {}
@property (nonatomic, copy) void(^requestLoading)(FBRequest*);
@property (nonatomic, copy) void(^requestDidReceiveResponse)(FBRequest*,NSURLResponse*);
@property (nonatomic, copy) void(^requestDidFailWithError)(FBRequest*,NSError*);
@property (nonatomic, copy) void(^requestDidLoad)(FBRequest*,id);
@property (nonatomic, copy) void(^requestDidLoadRawResponse)(FBRequest*,NSData*);
@end

Then use an implementation like this:

@implementation FBRequestBlockDelegate
@synthesize requestDidFailWithError, requestDidLoad, requestLoading, requestDidLoadRawResponse, requestDidReceiveResponse;
- (void)requestLoading:(FBRequest*)request
{
    if (self.requestLoading) self.requestLoading(request);
}
- (void)request:(FBRequest*)request didReceiveResponse:(NSURLResponse*)response
{
    if (self.requestDidReceiveResponse) self.requestDidReceiveResponse(request, response);
}
- (void)request:(FBRequest*)request didFailWithError:(NSError*)error
{
    if (self.requestDidFailWithError) self.requestDidFailWithError(request, error);
}
- (void)request:(FBRequest*)request didLoad:(id)result
{
    if (self.requestDidLoad) self.requestDidLoad(request,result);
}
- (void)request:(FBRequest*)request didLoadRawResponse:(NSData*)data
{
    if (self.requestDidLoadRawResponse) self.requestDidLoadRawResponse(request,data);
}
-(void)dealloc {
    self.requestDidFailWithError = nil;
    self.requestDidLoad = nil;
    self.requestDidLoadRawResponse = nil;
    self.requestDidReceiveResponse = nil;
    self.requestLoading = nil;
    [super dealloc];
}
@end

Now you can bundle the delegate code right next to the request. It only has to handle the current case, so no massive sequence of unnecessary if-statements.

    FBRequestBlockDelegate *delegate = [FBRequestBlockDelegate new];
    delegate.requestDidLoad = ^(FBRequest *request, id result) {
        // Process this particular request
        [delegate release];
    };

    [self.facebook requestWithGraphPath:@"some path"
                            andDelegate:delegate];

Don’t forget that delegates aren’t usually retained by the class it is a delegate of, so a good idea is to release the delegate at the end of the last that will be called block.

A brief history of ACM-SPPC T-shirts, and more

Yesterday was the South-Pacific region event for the annual ACM ICPC. You can read more about it in general at http://cm.baylor.edu/welcome.icpc and our regional at http://sppcontest.org/.

Every year, among the IBM-branded schwag that the members of competing teams receive for their five hours of keyboard-mashing, swearing, headdesking and facepalming, is a t-shirt. Shirts are also given to the organisers and are generally a different colour. This is an attempt to chronicle the various colours of competitor shirt given out over recent years. Continue reading

Ghetto Text Editing

I realised yesterday that one factor consistently ignored in the old vi/emacs/butterflies debate…is how “ghetto” the method of text editing is, i.e. how degenerate given the available tools. Old terminal-based editors can seem quite ghetto compared to modern GUI-based ones, but after thinking about it you can do a whole lot better.

There are many favourites of mine in the ghetto text editing category:

  • Write your text in a title for a component in SSIS, switch to code view and copy your text out.
  • Write your own text editor.
  • Write your own text editor in machine code, with another text editor.
  • If you are using a GUI designer for your own text editor, preload the text field with the text you are writing and then copy it out from the backend code.
  • Write a LaTeX document with your text, typeset it to a PDF, open the results and copy your text out.
  • Use Word…ugh, very ghetto.
  • Write a Word macro that generates your text into a WordArt instance.
  • Find the minimum-order polynomial function which produces desired ASCII values given values in some countable set.
  • Write your text in the frequency domain. Record the Fourier transform or number-theoretic transform of your text.
  • Factor your text into primes.
  • Create your own font, where the entire text is rendered with a single codepoint.
  • When it comes time to print your text document, order something online and copy the text to the description field of the order form—then it will appear on the attached invoice.
  • Or, have your name changed, then your text will appear in the electoral roll.

I’m quite certain you can think up some more…