Objective-C: передать селектор в качестве параметра, а затем вызвать его - PullRequest
7 голосов
/ 16 августа 2011

Я пытаюсь передать селектор в качестве параметра и выполнить его позже. Но я получаю ошибку SIGABRT, когда пытаюсь вызвать селектор со следующей ошибкой в ​​консоли:

Завершение приложения из-за необработанного исключения 'NSInvalidArgumentException', причина: '- [HttpRequest OnFinishConn:]: нераспознанный селектор отправлен на экземпляр 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]);
}

Я новичок в цели c, поэтому наберитесь терпения.

Ответы [ 3 ]

7 голосов
/ 16 августа 2011

Это потому, что вы пытаетесь использовать шаблон target-action , но не проходите цель. Я бы порекомендовал подход делегата, но вот пример того, как должен выглядеть ваш интерфейс.

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

Убедитесь, что вы не сохраняете onEndTarget, потому что это может создать цикл сохранения. Также рассмотрите возможность назначения цели свойством, чтобы, если что-то было сделано с соединением до его завершения, оно перестало быть делегатом.

4 голосов
/ 16 августа 2011

Вы отправляете селектор на self, но это в HttpRequest. Селектор, который вы пытаетесь вызвать, находится в AppDelegate. Итак, вы отправляете селектор объекту, который его не реализует. Чтобы исправить это, вы должны хранить не только селектор, но и указатель на объект, на который должен быть отправлен селектор.

0 голосов
/ 16 августа 2011

Пожалуйста, прочитайте документацию по NSInvocation или передайте блок в качестве параметра, если ваша целевая ОС поддерживает его.

...