2009-05-31 143 views
51

,具体方法:如何将@selector作为参数传递?

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

我如何通过在@选择?我尝试将它转换为(id)以使其编译,但它在运行时崩溃。


更具体而言,我有一个这样的方法:

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

它崩溃。我该如何传入选择器而不会崩溃,以便在线程准备就绪时新线程可以调用选择器?

回答

67

这里的问题是没有将选择器传递给方法本身,而是将选择器传递到预期对象的位置。要将非对象值作为对象传递,可以使用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 
+0

+50非常好!我永远不会记得如何做到这一点...... – bentford 2012-03-17 00:10:44

+0

为什么你必须用新线程做那一点? – cstack 2012-09-07 15:13:40

+2

@cstack:如果你看到这个问题,产生一个新的线程是他正在尝试做的事情。所以我在我的例子中使用了相同的任务。但是这种技术并不是特定于产生新线程的特定方式。 – Chuck 2012-09-07 15:31:35

0

如果你不想指定对象只使用零。

[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]; 
} 
+0

请查看更新的问题。谢谢! – erotsppa 2009-05-31 21:03:40

4

使用NSValue,就像这样:

+(void)method1:(SEL)selector { 
    NSValue *selectorValue = [NSValue value:&selector withObjCType:@encode(SEL)]; 
    [NSThread detachNewThreadSelector:@selector(method2:) 
          toTarget:self 
          withObject:selectorValue]; 
} 

NSValue的目的是作为一个对象的包装任意非对象类型。

41

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