views:

199

answers:

4

Hello! I am writing a simple application using the Facebook iPhone SDK. The Facebook code is mostly asynchronous, I start an operation and receive the response asynchronously in a delegate call:

- (void) doSomething {
    [FBSomething startOperationWithDelegate:self];
}

- (void) fbOperationFinished: (FBSomething*) operation {…}

Quite often there are more instances of a given operation (say FBRequest) that use the same callback. This means that I have to put a conditional clause into the callback handler to know which of these operations finished.

This leads to messy, a kind of “asynchronous spaghetti code” monster because the code is full of conditionals and it’s almost impossible to see the program flow logic. Is there a better way to write such code? (It’s a shame we don’t have blocks on iPhone.) I thought about introducing a simple state machine, but I’m not sure it will help.

+8  A: 

I'm not familiar with the Facebook SDK, but you could just create a subclass that implements the FBRequestDelegate protocol (if it's called like that) for every specific task you need Facebook for. This way, you have say 5 classes implementing - fbOperationFinished: rather than one class with 5 different execution paths separated by ifs or switches.

MrMage
+1 Yes, this is the way to do it. If the task are discrete enough to require significant branching, they are discrete enough to be encapsulated in their own class. Remember that delegates attach to instances, not classes. You can have as many instances of the delegate as needed.
TechZen
The problem is that the tasks themselves are not discrete enough to require decoupling into separate classes. If the code were synchronous, there would be almost no branching at all. I am hesitant to create multiple classes and share the member variables just to get a decent program flow.
zoul
…but yes, you’re right, this will do.
zoul
+1  A: 

(It’s a shame we don’t have blocks on iPhone.)

You can create a visual block using curly brackets without a symbol. For example, animation blocks have no visual structure but you can supply it like this:

// ...some code
[UIView beginAnimations:@"selectionAnimation" context:nil];{
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:0.1];
    [UIView setAnimationRepeatCount:1];
    [UIView setAnimationRepeatAutoreverses:YES];
    { //start properties to animate
        self.transform=CGAffineTransformScale(self.transform, 1.1, 1.1);
    } // end properties to animate
    [UIView commitAnimations];
}
// more code...

It's not a logical block but it's better than nothing. You can also use them to fold code. I use them to hide assertions or debug code.

TechZen
@TechZen: "Blocks" is one of the Apple's strange terms for "Closures".
KennyTM
Sorry, I did hesitate a second between ‘closures’ and ‘blocks’. Does anyone know why they chose yet another term for something that already has a widely accepted name?
zoul
This has nothing to do with blocks.
St3fan
Animation "blocks" appear to small talk like constructions so I imagine that is where the term comes from. I would also point out that before small talk influenced languages like Ruby were popular, "block" just meant any delimited section of code. It didn't have to be a functional unit.
TechZen
+2  A: 

There is no need to subclass the Facebook API objects. I would highly recommend against that.

All the facebook objects have a userInfo field that you can use to store request specific information. So you can store something in there to identify the request or even a reference to an object to deal with the request.

That is much cleaner and more in the style of the Cocoa frameworks.

St3fan
A: 

I would put these requests into an NSOperationQueue, this keeps each one distinct and also throttles how many you have active at once.

You just need to wrap the requests into an NSOperation object (which the Facebook API may have already?)

Kendall Helmstetter Gelner