Reputation: 585
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
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