如何将@selector作为参数传递?

51

对于该方法:

[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:(id)SELECTOR];

如何传递一个 @selector?我尝试将其转换为 (id) 以使其编译通过,但会在运行时崩溃。


更具体地说,我有一个像这样的方法:

+(void)method1:(SEL)selector{
[NSThread detachNewThreadSelector:@selector(method2:) toTarget:self withObject:selector];   
}

它崩溃了。如何在不崩溃的情况下传入选择器,以便当线程准备好时,新线程可以调用该选择器?

5个回答

69

这里的问题不是把一个选择器传递给一个方法,而是在需要对象的地方传递了一个选择器。要将非对象值作为对象传递,您可以使用 NSValue。在这种情况下,您需要创建一个接受 NSValue 并检索适当选择器的方法。以下是一个示例实现:

@implementation Thing
- (void)method:(SEL)selector {
    // Do something
}

- (void)methodWithSelectorValue:(NSValue *)value {
    SEL selector;

    // Guard against buffer overflow
    if (strcmp([value objCType], @encode(SEL)) == 0) {
        [value getValue:&selector];
        [self method:selector];
    }
}

- (void)otherMethodShownInYourExample {
    SEL selector = @selector(something);
    NSValue *selectorAsValue = [NSValue valueWithBytes:&selector objCType:@encode(SEL)];
    [NSThread detachNewThreadSelector:@selector(methodWithSelectorValue:) toTarget:self withObject:selectorAsValue];
}
@end

2
@cstack:如果你看一下问题,生成一个新线程是OP试图做的事情。所以我在我的例子中使用了同样的任务。但这种技术并不特定于生成新线程。 - Chuck

43
你可以使用 NSStringFromSelector()NSSelectorFromString() 函数在选择器和字符串对象之间进行转换。因此,你可以仅传递字符串对象。
或者,如果你不想更改你的方法,你可以创建一个 NSInvocation 来创建方法调用的调用(因为它可以设置具有非对象参数的调用),然后调用它可以使用 [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];

这是最好的答案,希望能有更多的人给它点赞。 - Praveen S
这是更简单的方法 - 在我看来,它应该是被选择的答案。 - roocell

4
使用NSValue,如下所示:
+(void)method1:(SEL)selector {
    NSValue *selectorValue = [NSValue value:&selector withObjCType:@encode(SEL)];
    [NSThread detachNewThreadSelector:@selector(method2:) 
                             toTarget:self 
                           withObject:selectorValue];
}

NSValue是一个对象包装器,用于任意非对象类型。


我相信你漏掉了在"selector"之前加一个"&"符号,这样它最终应该是"... value:&selector ..."而不是"... value:selector ..."。 - Senseful

2

0

如果您不想指定对象,只需使用nil。

[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:nil];

如果您需要将一个对象传递给选择器,代码应该类似于这样。
在这里,我将一个字符串传递给方法“setText”。
NSString *string = @"hello world!";
 [NSThread detachNewThreadSelector:@selector(setText:) toTarget:self withObject:string];


-(void)setText:(NSString *)string {
    [UITextField setText:string]; 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接