Objective-C: Pass selector as parameter and then call it

14,714

Solution 1

That is because you are trying using the target-action pattern but not passing a target. I would actually recommend the delegate approach but here is an example of what your interface should look like.

@interface HttpRequest : NSObject
{
    @private 
    id onEndTarget; //<- need to know who to send the message to (do not retain)
    SEL onEndSel;
    NSMutableData* receivedData;
}

//Accept the target here
-(void) StartRequest:(NSString *) url 
          parameters:(NSString*) params 
           onEndTarget:(id)target
            onEndSelector:(SEL) selector;

//... implementation

-(void) connectionDidFinishLoading:(NSURLConnection*) connection
{
    [onEndTarget performSelector:onEndSel withObject:[[NSMutableData alloc] initWithData:receivedData]];
}

//...
//Inside App Delegate
[req StartRequest:url parameters:@"a" onEndTarget:self onEndSelector:@selector(OnFinishConn:)];

Make sure you do not retain the onEndTarget because that could create a retain cycle. Also consider making the target a property so if something is done with the connection before it complete it can stop being the delegate.

Solution 2

You're sending the selector to self, but that's in HttpRequest. The selector you're trying to call is in AppDelegate. So you're sending the selector to an object that doesn't implement it. To fix, you should store not just the selector but a pointer to the object to which the selector should be sent.

Share:
14,714

Related videos on Youtube

Payn3
Author by

Payn3

Updated on June 04, 2022

Comments

  • Payn3
    Payn3 about 2 years

    i'm trying to pass a selector as a parameter and execute it later. But i get a SIGABRT error when i try to call the selector with the next error in console:

    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[HttpRequest OnFinishConn:]: unrecognized selector sent to instance 0x7834c80'

    HttpRequest.h

    #import <Foundation/Foundation.h>
    
    @interface HttpRequest : NSObject
    {
        @private SEL onEndSel;
        @private NSMutableData* receivedData;
    }
    -(void) StartRequest:(NSString *) url 
              parameters:(NSString*) params 
                onEndSelector:(SEL) selector;
    @end
    

    HttpRequest.m

    #import "HttpRequest.h"
    
    @implementation HttpRequest
    
    -(void) StartRequest:(NSString *)url 
              parameters:(NSString*)params
              onEndSelector:(SEL)selector
    {
        receivedData = [[NSMutableData alloc] init];
        NSMutableURLRequest *request = 
        [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
        [request setHTTPMethod:@"POST"];
        [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
        onEndSel = selector;
        NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    
    
    }
    -(void) connectionDidFinishLoading:(NSURLConnection*) connection
    {
        //NSLog([[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding]);
        [self performSelector:onEndSel withObject:[[NSMutableData alloc] initWithData:receivedData]];
    }
    -(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
        [receivedData appendData:data];    
    }
    @end
    

    AppDelegate.m

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        //self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
        //self.window.backgroundColor = [UIColor whiteColor];
        HttpRequest* req = [[HttpRequest alloc] init];
        SEL mysel = @selector(OnFinishConn:);
        NSString * url = [[NSString alloc] initWithString:@"http://www.google.es"];
        [req StartRequest:url parameters:@"a" onEndSelector:@selector(OnFinishConn:)];
        [self.window makeKeyAndVisible];
    
        return YES;
    }
    -(void)OnFinishConn:(NSMutableData *)data
    {
        NSLog([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }
    

    I'm new in objective c, so please be patient.

  • Payn3
    Payn3 almost 13 years
    Thanks all for your responses. It worked well with Joe's code.
  • Joe
    Joe almost 13 years
    Glad they helped be sure to mark a question as answered once your problem is resolved and welcome to StackOverflow!.
  • Logicsaurus Rex
    Logicsaurus Rex about 7 years
    Brillliant. This should be the answer