Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a delegate-based callback system into block-based?

I have a class, which has a delegate based system for sending different type of requests. it uses delegate to tell the object when the request is complete and also if it was a success o an error.

Now, I also have to check what type of request was it in response to take appropriate action.

I have wrapper class that should give me a block based interface for the same.

I pass a completion-block and an error-block to a request method which should internally use this delegate based class.

And when the response comes, should automatically call the appropriate handler for that request type and depending on success and error as well.

I saw a similar question on SO, but it was a little unclear to me, So please give a general idea of how to go about it instead of marking it as duplicate straight away.

like image 260
Amogh Talpallikar Avatar asked Jan 04 '13 11:01

Amogh Talpallikar


2 Answers

Here is one way to do it. Use this RAExpendable class to dynamically build a delegate with a block based implementation.

Let's say your delegate is:

@protocol XDelegate
-(void) foo:(id)response;
@end

Add RAExpendable.h, RAExpendable.m from https://github.com/evadne/RAExpendable to your project. Dynamically add the delegate method:

    RAExpendable *expendable = [RAExpendable new];
    [expendable addMethodForSelector:@selector(foo:) types:"v@:@" block:^(id x, SEL sel, id response){
        NSLog(@"response is %@", response);
    }];

And set the expendable class as your delegate:

    someObject.delegate = expendable;

Now, if you do this:

    [expendable performSelector:@selector(foo:) withObject:@"OK"];

You get the string response is OK. Replace NSLog with whatever success/failure implementation you see fit. From now on, when you call foo:, the block executes instead.

If you want to modify this for your use case, note that the parameters for this example were v@:@, which according to the Type Encoding guide of the runtime means: void return, self, SEL, object. self and SEL are the two hidden parameters present on every Objective-C methods, the third parameter is the first non hidden parameter of the method. The signature of the block has to match the signature of the method.

like image 161
Jano Avatar answered Oct 04 '22 06:10

Jano


With REKit, you can make a delegate dynamically like below:

id dynamicDelegate;
dynamicDelegate = [[NSObject alloc] init];
[dynamicDelegate respondsToSelector:@selector(foo:) withKey:nil usingBlock:^(id receiver, id response) {
    NSLog(@"response is %@", response);
}];
someObject.delegate = dynamicDelegate;
like image 22
Kazki Avatar answered Oct 04 '22 07:10

Kazki