2009-05-31 33 views
51

Dla metody:Jak przekazać @selector jako parametr?

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

Jak mogę przekazać w @selector? Próbowałem przesłać go do (id), aby go skompilować, ale ulega awarii w czasie wykonywania.


Dokładniej, mam metody takie jak to:

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

się zawiesi. Jak przekazać selektor bez awarii, aby nowy wątek mógł wywołać selektor, gdy wątek jest gotowy?

Odpowiedz

67

Problemem tutaj nie jest przekazywanie selektora do metody jako takiej, ale przekazywanie selektora tam, gdzie obiekt jest oczekiwany. Aby przekazać wartość nieobiektową jako obiekt, można użyć NSValue. W takim przypadku musisz utworzyć metodę, która akceptuje wartość NSV i pobiera odpowiedni selektor. Oto przykład realizacja:

@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 Doskonale! Nigdy nie pamiętam, jak to zrobić ... – bentford

+0

Dlaczego musisz zrobić to samo z nowym wątkiem? – cstack

+2

@cstack: Jeśli spojrzysz na to pytanie, stworzenie nowego wątku jest tym, co próbował OP. Więc użyłem tego samego zadania w moim przykładzie. Ale ta technika nie jest w żaden sposób specyficzna dla stworzenia nowego wątku. – Chuck

0

Jeśli nie chcesz, aby określić przedmiot wystarczy użyć zero.

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

Jeśli chcesz przekazać obiekt do selektora, wyglądałoby to tak.

Tutaj przekazuję ciąg do metody "setText".

NSString *string = @"hello world!"; 
[NSThread detachNewThreadSelector:@selector(setText:) toTarget:self withObject:string]; 


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

proszę zobaczyć zaktualizowane pytania. Dziękuję Ci! – erotsppa

4

Zastosowanie NSValue, tak:

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

NSValue przeznaczony jest jako obiekt-otoczka do dowolnych typów non-object.

+0

Uważam, że brakuje "znaku" przed "selektorem", więc kończy się on "... wartością: & selektorem ..." zamiast "... wartością: selektorem ...". – Senseful

+0

Prawda. Dzięki za uwagę; Naprawiłem to. –

41

Można konwertować między selektorami i obiektami typu string za pomocą funkcji NSStringFromSelector() i NSSelectorFromString(). Więc możesz po prostu przekazać obiekty typu string.

Alternatywnie, jeśli nie chcesz zmieniać swoich metod, możesz utworzyć NSInvocation, aby utworzyć wywołanie dla wywołania metody (ponieważ może ono wywoływać wywołania z argumentami nieobiektowymi), a następnie wywoływać je [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];

+0

To wymaga więcej upvotes –

+0

To jest najlepsza odpowiedź, chciałbym, aby więcej osób mogło ją upomnieć. –

+0

Wielkie dzięki, to było właśnie to, czego potrzebowałem. – amergin

Powiązane problemy