2011-08-16 10 views
5

Estoy tratando de pasar un selector como parámetro y ejecutarlo más tarde. Pero me sale un error de SIGABRT cuando intento llamar el selector con el siguiente error en la consola:Objetivo-C: Pase el selector como parámetro y luego llámelo

Terminación de aplicación debido a excepción no detectada 'NSInvalidArgumentException', razón: '- [HttpRequest OnFinishConn:]: selector no reconocido enviado a la instancia 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]); 
} 

Soy nuevo en Objective C, así que por favor sea paciente.

+0

Si bien no es la respuesta a su pregunta, el hecho de que esta pregunta, me lleva a recomendar que pruebe ASIHttpRequest, en lugar de reinventar la rueda – Jonathan

Respuesta

6

Esto se debe a que está intentando usar el patrón target-action pero no pasa un objetivo. En realidad, recomendaría el enfoque de delegado, pero aquí hay un ejemplo de cómo debería ser su interfaz.

@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:)]; 

Asegúrate de no conservar el onEndTarget porque eso podría crear un ciclo de retención. También considere convertir el objetivo en una propiedad, de modo que si se hace algo con la conexión antes de que se complete, puede dejar de ser el delegado.

+0

Gracias a todos por sus respuestas. Funcionó bien con el código de Joe. – Payn3

+0

Me alegro de que hayan ayudado a asegurarse de marcar una pregunta como respondida una vez que se resuelva su problema y ¡bienvenido a StackOverflow !. – Joe

4

Está enviando el selector a self, pero eso está en HttpRequest. El selector al que intenta llamar está en AppDelegate. Entonces estás enviando el selector a un objeto que no lo implementa. Para solucionarlo, debe almacenar no solo el selector sino un puntero al objeto al que se debe enviar el selector.

1

Lea la documentación en NSInvocation o pase un bloque como parámetro si su sistema operativo objetivo lo admite.

+0

Brillante. Esta debería ser la respuesta –

Cuestiones relacionadas