@selector中的参数

时间:2009-08-28 22:43:40

标签: iphone cocoa cocoa-touch

有没有办法可以在选择器中传递参数?

示例: 我有这个方法

- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

我需要通过一个传递两个参数的选择器来调用这个函数。

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES];

我该怎么做?

5 个答案:

答案 0 :(得分:56)

您可以使用NSTimer方法:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
                                 invocation:(NSInvocation *)invocation
                                    repeats:(BOOL)repeats;

相反,因为NSInvocation对象将允许您传递参数;一个NSInvocation对象,docs定义它:

  

呈现静态的Objective-C消息,也就是说,它是一个变成对象的动作。

使用选择器创建NSTimer对象时,方法的格式为:

- (void)timerFireMethod:(NSTimer*)theTimer

NSInvocation允许您设置目标,选择器和传入的参数:

SEL selector = @selector(myMethod:setValue2:);

NSMethodSignature *signature = [MyObject instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];

NSString *str1 = @"someString";
NSString *str2 = @"someOtherString";

//The invocation object must retain its arguments
[str1 retain];
[str2 retain];

//Set the arguments
[invocation setTarget:targetInstance];
[invocation setArgument:&str1 atIndex:2];
[invocation setArgument:&str2 atIndex:3];

[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES];

MyObject是在myMethod:setValue2:上声明和实现instanceMethodSignatureForSelector:的类,NSObject上是一个在NSMethodSignature上声明的便捷函数,它返回一个NSInvocation对象你,被传递给setArgument:atIndex:

另外,要注意,使用{{1}},要传递给方法的参数的索引设置为选择器从索引2开始。来自docs:

  

指数0和1分别表示隐藏的参数self和_cmd;您应该使用setTarget:和setSelector:方法直接设置这些值。对通常在消息中传递的参数使用索引2和更大。

答案 1 :(得分:27)

对于scheduledTimerWithTimeInterval:,您传递的选择器只能有一个参数。此外,它的一个参数必须是NSTimer *对象。换句话说,选择器必须采用以下形式:

- (void)timerFireMethod:(NSTimer*)theTimer

你可以做的是将参数存储在userInfo字典中,并从计时器回调中调用你想要的选择器:

- (void)startMyTimer {
    /* ... Some stuff ... */
    [NSTimer scheduledTimerWithTimeInterval:0.1 
                                     target:self 
                                   selector:@selector(callMyMethod:) 
                                   userInfo:[NSDictionary dictionaryWithObjectsAndKeys:someValue, 
                       @"value1", someOtherValue, @"value2", nil] 
                                    repeats:YES];
}

- (void)callMyMethod:(NSTimer *)theTimer {
    NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];
    NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];
    [self myMethod:value1 setValue2:value2];
}

答案 2 :(得分:2)

看起来像块的工作(假设这是针对Snow Leopard的。)

-jcr

答案 3 :(得分:0)

块现在似乎是一个明显的答案......但是在经典运行时中还有另一个非常常见的习惯用法,在单个对象中挑选你的参数:

 - (void)doMyMethod:(NSDictionary *)userInfo
 {
     [self myMethod: [userInfo objectForKey:@"value1"] setValue2: [userInfo objectForKey:@"value2"]];
 }
 - (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

现在您可以发送到

[self performSelector:@selector(doMyMethod:) withObject:@{@"value1":@"value1",@"value2":@"value2"}];

答案 4 :(得分:-2)

@selector(myMethod:setValue2:)

由于您的方法的选择器不仅称为myMethod,而是myMethod:setValue2:

另外(我可能会离开这里),我相信在技术上你可以删掉冒号之间的单词,因此也可以使用@selector(myMethod::),但除非其他人可以确认,否则不要引用我。