2009-05-31 5 views
51

Для метода:Как передать @selector в качестве параметра?

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

Как передать в @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

+0

Почему вы должны сделать это с новым потоком? – cstack

+2

@cstack: Если вы посмотрите на вопрос, создавая новый поток, то, что он пытался сделать OP. Поэтому в моем примере я использовал ту же задачу. Но эта техника никак не связана с созданием нового потока. – Chuck

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

4

Использование NSValue, например, так:

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

NSValue предназначен как объектно-обертка для произвольных типов необъектных.

+0

Я считаю, что перед «селектором» вы не указали знак «&», чтобы он оказался «... значение: & selector ...» вместо «... value: selector ...». – Senseful

+0

Правда. Спасибо, что заметили; Я исправил это. –

41

Вы можете преобразовать между селекторами и строковыми объектами с помощью функций NSStringFromSelector() и NSSelectorFromString(). Таким образом, вы можете просто передать строковые объекты.

Альтернативно, если вы не хотите изменять свои методы, вы можете создать NSInvocation для создания вызова для вызова метода (поскольку он может настраивать вызовы с аргументами, отличными от объекта), а затем называть его [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];

+0

Этого нужно больше upvotes –

+0

Это лучший ответ на лот, хотелось бы, чтобы я мог увеличить число людей, чтобы повысить этот показатель. –

+0

Огромное спасибо, это было именно то, что мне нужно. – amergin