2011-08-16 27 views
5

我想將選擇器作爲參數傳遞並稍後執行。但我得到一個SIGABRT錯誤,當我嘗試在控制檯下一個錯誤調用選擇:Objective-C:傳遞選擇器作爲參數,然後調用它

終止應用程序由於未捕獲的異常 「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新的,所以請耐心等待。

+0

雖然這不是您的問題的答案,但您提出這個問題的事實,導致我建議您嘗試使用ASIHttpRequest,而不是重新發明輪子 – Jonathan

回答

6

這是因爲您正在嘗試使用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,因爲這可能會創建一個保留週期。另外考慮將目標作爲一個屬性,所以如果在連接完成之前完成了連接,它可以停止成爲代理。

+0

感謝您的回覆。它與Joe的代碼運作良好。 – Payn3

+0

很高興他們幫助確保將問題標記爲解決問題並歡迎使用StackOverflow! – Joe

4

您正在發送選擇器到self,但這是在HttpRequest中。你試圖調用的選擇器在AppDelegate中。所以你將選擇器發送給一個沒有實現它的對象。要解決這個問題,你應該存儲不僅僅是選擇器,而是存儲一個指向選擇器應該發送到的對象的指針。

1

如果您的目標操作系統支持它,請閱讀NSInvocation上的文檔或傳遞塊作爲參數。

+0

Brillliant。這應該是答案 –

相關問題