Как передать @selector в качестве параметра? - PullRequest
51 голосов
/ 01 июня 2009

Для метода:

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

Как мне пройти в @selector? Я попытался привести его к (id), чтобы он скомпилировался, но во время выполнения происходит сбой.


Точнее, у меня есть такой метод:

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

Вылетает. Как передать селектор без сбоев, чтобы новый поток мог вызвать селектор, когда поток готов?

Ответы [ 5 ]

67 голосов
/ 01 июня 2009

Проблема здесь не в том, чтобы передать селектор методу как таковой, а в том, чтобы передать селектор там, где ожидается объект. Чтобы передать не объектное значение в качестве объекта, вы можете использовать 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
42 голосов
/ 23 апреля 2011

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

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

4 голосов
/ 01 июня 2009

Используйте NSValue, вот так:

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

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

2 голосов
/ 01 июня 2009
0 голосов
/ 01 июня 2009

Если вы не хотите указывать объект, просто используйте 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]; 
}
...