Objective-C:将选择器作为参数传递,然后调用它

发布于 2024-11-30 08:15:38 字数 2367 浏览 0 评论 0原文

我正在尝试将选择器作为参数传递并稍后执行。但是当我尝试调用选择器并在控制台中出现下一个错误时,我收到 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 的新手,所以请耐心等待。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不顾 2024-12-07 08:15:38

这是因为您正在尝试使用 目标-动作模式但未传递目标。我实际上会推荐委托方法,但这里是您的界面应该是什么样子的示例。

@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,因为这可能会创建保留周期。还可以考虑将目标设置为属性,以便如果在连接完成之前对连接进行了某些操作,则它可以不再是委托。

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.

想念有你 2024-12-07 08:15:38

您将选择器发送给 self,但那是在 HttpRequest 中。您尝试调用的选择器位于 AppDelegate 中。因此,您将选择器发送到未实现它的对象。要解决此问题,您不仅应该存储选择器,还应该存储指向选择器应发送到的对象的指针。

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.

奢华的一滴泪 2024-12-07 08:15:38

请阅读有关 NSInitation 的文档或传递如果您的目标操作系统支持,则将块作为参数。

Please read documentations on NSInvocation or pass a block as a parameter if your target OS support it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文