我正在尝试将选择器作为参数传递并稍后执行。但是当我尝试使用控制台中的下一个错误调用选择器时,我收到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的新手,所以请耐心等待。
答案 0 :(得分:7)
这是因为您尝试使用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,因为这可能会创建一个保留周期。还要考虑使目标成为属性,这样如果在完成连接之前完成某些操作,它就可以不再是委托了。
答案 1 :(得分:4)
您将选择器发送到self
,但这是在HttpRequest中。您尝试调用的选择器位于AppDelegate中。所以你将选择器发送到一个没有实现它的对象。要修复,您不仅应该存储选择器,还应该存储指向应该将选择器发送到的对象的指针。
答案 2 :(得分:0)
如果目标操作系统支持,请阅读NSInvocation上的文档或将块作为参数传递。