SEL performSelector和arguments

时间:2010-04-26 19:12:20

标签: iphone objective-c selector

当你拥有一个SEL对象时,似乎应该有一种简单的方法来调用带有一些参数的选择器。我似乎无法找到正确的语法。

-(MyClass*) init: (SEL)sel owner:(NSObject*) parent
{
   int i =10;
   [parent performSelector:sel:i  ];
}

5 个答案:

答案 0 :(得分:76)

查看NSObject文档。在这种情况下:

[parent performSelector:sel withObject:[NSNumber numberWithInt:i]];

(请注意,此方法实际列在NSObject protocol文档中)。由于-[NSObject performSelector:withObject:]需要一个对象参数,因此您必须在父类的类中编写一个包装器,如

-(void)myMethodForNumber:(NSNumber*)number {
    [self myMethod:[number intValue]];
}

取消装箱NSNumber

如果您确实想要调用直接获取非对象参数的方法(例如,您无法控制被调用者源并且不想添加类别),则可以使用{{3} }:

NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:parent];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv invoke];

另外,您的方法看起来像init方法,但不遵循Objective-C的正确初始化模式。您需要调用超类初始值设定项,并且需要测试该调用的nil结果,并且必须从初始化方法返回self。在所有情况下,Objective-C初始化方法应如下所示:

-(id)myInitMethod {
    self = [super init];
    if(self != nil) {
      //perform initialization of self
    }

    return self;
}

您的方法(如果它是一个init方法)将如下所示:

-(id) init: (SEL)sel owner:(NSObject*) parent
{
   self = [super init];
   if(self != nil) {
       int i = 10;
       NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]];
       [inv setSelector:sel];
       [inv setTarget:parent];
       [inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
       [inv invoke];
   }

    return self;
}

要在风格上更加符合Objective-C,我也会重命名初始值设定项-(id)initWithSelector:owner:

答案 1 :(得分:12)

Barry Wark说的很棒..我刚刚修改了懒惰程序员的讨论

-(void)myMethodWith:(int)number andBOOL:(BOOL) someBool andStr:(NSString *)str{
    NSLog(@"%d %d %@",number,someBool,str);
}

-(void) testMethod{
    SEL sel = @selector(myMethodWith:andBOOL:andStr:);
    int i = 10;
    BOOL bol = YES;
    NSString *str = @"hey baby !";
    NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:sel]];
    [inv setSelector:sel];
    [inv setTarget:self];
    [inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
    [inv setArgument:&bol atIndex:3];
    [inv setArgument:&str atIndex:4];
    [inv invoke];
}

答案 2 :(得分:3)

你想使用performSelector:withObject:棘手的部分是将int转换为NSObject。您不能将performSelector与使用int参数的邮件一起使用,而是必须使用id

来自NSObject Protocol Reference

  

aSelector应该标识一个采用id类型的单个参数的方法。对于具有其他参数类型和返回值的方法,请使用NSInvocation

完成更改后,您可以执行以下操作:

id arg = [NSNumber numberWithInt:10];    
[parent performSelector:sel withObject:arg];

答案 3 :(得分:1)

对于将一个或两个id类型的对象作为参数的方法,您可以使用:

[parent performSelector:sel withObject:argument1];

[parent performSelector:sel withObject:argument1 withObject:argument2];

对于具有其他参数类型的方法,创建一个可以封装任意方法调用的NSInvocation

答案 4 :(得分:1)

您可以使用:

- (id)performSelector:(SEL)aSelector withObject:(id)anObject
- (id)performSelector:(SEL)aSelector withObject:(id)anObject  withObject:(id)anotherObject

或者,如果您需要使用更复杂的方法,请使用NSInvocation