Tejas
Tejas

Reputation: 585

Callback function in iOS using performSelector

I am trying to create a method which invokes the callback function of the callee in iOS. After browsing for dynamic function calling, here's what i tried:-

Header:-

+(void)url:(NSString *)url handler:(NSObject *)handler callback:(NSString *)callbackfn;

Implementation:-

+(void)url:(NSString *)url handler:(NSObject *)handler callback:(NSString *)callbackfn{
NSURLRequest *imageLoader = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];

[NSURLConnection sendAsynchronousRequest:imageLoader queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    SEL s = NSSelectorFromString(callbackfn);
    if ([handler respondsToSelector:s]) {
        [handler performSelector:s];
    }else{
        NSLog(@"does not responds to handler %@",[handler self]);
    }


}];

}

The ViewController calling it:-

-(IBAction)loadImage:(id)sender{

NSString *url = @"https://s3.amazonaws.com/uifaces/faces/twitter/ateneupopular/128.jpg";
[NetCall url:url handler:self callback:@"imageRec"];

}

-(void)imageRec{
    NSLog(@"net call done");
}

But when the code is executed, it prints in LOG "does not responds to handler". Am I passing the function name in wrong way ?

Log:-

2014-08-19 17:54:58.419 Testing[2194:78586] does not responds to handler <ViewController: 0x7b16c390>

Upvotes: 0

Views: 944

Answers (1)

jbouaziz
jbouaziz

Reputation: 1493

If you're trying to get a callback from an asynchronous request, I suggest you to use block syntax. It's available for iOS4+.

+ (void)url:(NSString *)url callback:(void (^)(NSData *data))callback {
    NSURLRequest *imageLoader = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];

    [NSURLConnection sendAsynchronousRequest:imageLoader queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

        if (callback)
            callback(data);
    }];
}

And that's how you call it:

// __weak typeof(self) weakSelf = self;  
NSString *stringUrl = @"https://s3.amazonaws.com/uifaces/faces/twitter/ateneupopular/128.jpg";  
[MyViewController stringUrl callback:^(NSData *data) {

    // Do something here with *data*
    // __strong typeof(weakSelf) strongSelf = weakSelf;
}];

If you need to use self, use a weak reference or it's likely to keep strong references and might cause you issues. To help you build blocks, there's this website http://goshdarnblocksyntax.com/


If you still want to use the selector technique, here's the modified code:

+ (void)url:(NSString *)url handler:(NSObject *)handler selector:(SEL)selector {
    NSURLRequest *imageLoader = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];

    [NSURLConnection sendAsynchronousRequest:imageLoader queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if ([handler respondsToSelector:selector]) {
            [handler performSelector:selector];
        }else{
            NSLog(@"does not responds to handler %@", handler);
        }

    }];
}

And in your ViewController:

- (IBAction)loadImage:(id)sender {

    NSString *url = @"https://s3.amazonaws.com/uifaces/faces/twitter/ateneupopular/128.jpg";
    [NetCall url:url handler:self selector:@selector(imageRec)];
}

- (void)imageRec {
    NSLog(@"net call done");
}

Upvotes: 1

Related Questions