web-dev-qa-db-fra.com

Comment passer @selector en paramètre?

Pour la méthode:

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

Comment passer dans un @selector? J'ai essayé de le convertir en (id) pour le compiler, mais il se bloque au moment de l'exécution.


Plus spécifiquement, j'ai une méthode comme celle-ci:

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

Ça plante. Comment passer dans le sélecteur sans se planter, afin que le nouveau thread puisse appeler le sélecteur lorsque le thread est prêt?

51
erotsppa

Le problème ici n'est pas de passer un sélecteur à une méthode, mais de passer à un sélecteur lorsqu'un objet est attendu. Pour transmettre une valeur non-objet en tant qu'objet, vous pouvez utiliser NSValue . Dans ce cas, vous devez créer une méthode qui accepte une NSValue et récupère le sélecteur approprié. Voici un exemple d'implémentation:

@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
67
Chuck

Vous pouvez convertir des sélecteurs et des objets chaîne à l'aide des fonctions NSStringFromSelector() et NSSelectorFromString(). Vous pouvez donc simplement passer des objets chaîne à la place.

Sinon, si vous ne souhaitez pas modifier vos méthodes, vous pouvez créer un NSInvocation pour créer un appel pour votre appel de méthode (puisqu'il peut configurer des invocations avec des arguments non-objet), puis l'appelez do [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];

42
user102008

Utilisez NSValue, comme suit:

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

NSValue est conçu comme encapsuleur d’objets pour les types non-objets arbitraires.

4
BJ Homer
2
ennuikiller

Si vous ne voulez pas spécifier d'objet, utilisez nil.

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

Si vous devez passer un objet au sélecteur, cela ressemblerait à quelque chose comme ça.

Ici, je passe une chaîne à la méthode "setText".

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


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