2009-05-31 188 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];