Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with the lack of closures in Objective-C

Maybe it's just the fact that I've been using http://nodejs.org/ lately, but the lack of closures in Objective-C (iphone) has been really hard to work around.

For example, I'm creating service classes. Each service class can have several methods, each of which makes a different URL request. I can use the delegate pattern, but that means that I have to create a new service each time I want to call a method on it (because it has to store the delegate and selector for that request, and new method calls would overwrite them).

Even more difficult for me is the fact that I can't easily keep local variables around in the scope for a callback. I have to store anything I want to send back to the delegate on the service class itself, which makes it harder to have more than one method on each class.

How do you pros do it? Should I just quit whining and do it another way?

like image 619
Sean Clark Hess Avatar asked Mar 22 '10 18:03

Sean Clark Hess


3 Answers

Blocks, that were introduced into Objective-C recently, enable closures. The only problem is that you can't use them on iPhone. Here comes 3-rd party solution, Plausible Blocks - they bring this capability on iPhone too.

Update: the sample project using blocks on iPhone can be found here.

like image 106
zakovyrya Avatar answered Sep 29 '22 19:09

zakovyrya


Any time you find yourself needing multiple delegates, the answer is notifications.

For something like a service class you'd probably make a singleton, and notify interested parties when a service request was complete via a notification.

Not that blocks are not an interesting solution to that problem, it's just that I felt you should know there are alternatives.

like image 31
Kendall Helmstetter Gelner Avatar answered Sep 29 '22 20:09

Kendall Helmstetter Gelner


I'm not a pro, but I've been struggling with the same problem so here's the best I've got so far:

@interface MyCallback : NSObject
  id target;
  SEL action;
  id value1;
  id value2;
  ...
@end

When I need to call something that will notify me about completion I fill set target and action with the actual callback (usually "self" and a method) and stuff other values I will need later into value1..2..3 The callee hangs on to the MyCallback object and when time comes it calls the target/action and passes the MyCallback as a parameter. That's how I get my "closure".

To address your other problem here's an idea: create a class derived from NSURLConnection, called MYURLConenction, and only addition is a field of type "id", call it MyStuff. Then proceed to use MYURLConenction instead of NSURLConnection - when you make a network request you can stuff your data (such as an instance of MyCallback) into MyStuff and it will hang on to them for you. Therefore you will not need to create a new instance of your service class for each invocation.

This is actually not how I do it though - I simply created a generic MyHTTPRequest wrapper class that is the delegate of the NSURLConnection, it accepts a URL & NSString POST body, processes all the network stuff and returns an NSString result and an NSError to the caller - a little bit higher abstraction. It also stores MyStuff, so that service classes can remain singletones if they want to.

like image 35
DenNukem Avatar answered Sep 29 '22 18:09

DenNukem