@selector中的参数

isi*_*atz 35 iphone cocoa cocoa-touch

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

例如: 我有这个方法

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

}
Run Code Online (Sandbox Code Playgroud)

我需要通过传递两个参数的选择器来调用此函数.

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

我怎样才能做到这一点?

Ale*_*ski 56

你可以使用这个NSTimer方法:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
                                 invocation:(NSInvocation *)invocation
                                    repeats:(BOOL)repeats;
Run Code Online (Sandbox Code Playgroud)

相反,因为一个NSInvocation对象将允许你传递参数; 一个NSInvocation目的是,作为文档进行定义:

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

虽然NSTimer使用选择器创建对象需要方法的格式为:

- (void)timerFireMethod:(NSTimer*)theTimer
Run Code Online (Sandbox Code Playgroud)

An 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];
Run Code Online (Sandbox Code Playgroud)

声明和实现MyObject的类在哪里myMethod:setValue2:- instanceMethodSignatureForSelector:是声明的一个便利函数NSObject,返回一个NSMethodSignature对象,传递给它NSInvocation.

另外,需要注意的是setArgument:atIndex:,将参数的索引传递给方法集作为选择器从索引2开始.来自docs:

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

  • 注意,如果没有静态分配`str1`和`str2`,你就会泄漏它们.`NSTimer`被记录为将`-retainArguments`发送到它的调用对象,但是你自己将`-retainArguments`发送给调用对象也没什么坏处.问题是自己保留参数,然后告诉调用保留它们.不要自己保留调用参数!让调用处理它 - 并且,在这里,让计时器自己处理它. (3认同)
  • 不要像检索方法签名那样对`targetInstance`类进行硬编码.如果你真的想使用`+ instanceMethodSignatureForSelector:`,你可以使用`[[targetInstance class] instanceMethodSignatureForSelector:selector]`,但这是不必要的复杂 - 只需使用`[targetInstance methodSignatureForSelector:selector]向对象本身询问方法签名. . (3认同)

Mat*_*all 27

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

- (void)timerFireMethod:(NSTimer*)theTimer
Run Code Online (Sandbox Code Playgroud)

你可以做的是将参数存储在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];
}
Run Code Online (Sandbox Code Playgroud)

  • 这对于您在isiaatz上面发布的特定方法是正确的.如果这只是一个例子,你想知道如何将多个参数发送到选择器,请修改你的问题 (2认同)