35 votes

Des Arguments de @sélecteur

Est-il possible que je peux passer des arguments dans le sélecteur?

exemple: J'ai cette méthode

- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

et j'ai besoin d'appeler cette fonction par l'intermédiaire d'un sélecteur en passant par deux arguments.

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES];

Comment puis-je faire cela?

56voto

Alex Rozanski Points 26107

Vous pouvez utiliser l' NSTimer méthode:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
                                 invocation:(NSInvocation *)invocation
                                    repeats:(BOOL)repeats;

Au lieu de cela, depuis un NSInvocation objet vous permettra de passer des arguments; un NSInvocation objet est, comme les docs définir:

Objective-C message rendu statique, qui est, il est une action transformé en un objet.

Alors que la création d'un NSTimer objet à l'aide d'un sélecteur exige le format de la méthode:

- (void)timerFireMethod:(NSTimer*)theTimer

Un NSInvocation vous permet de définir la cible, le sélecteur, et les arguments que vous passez dans:

SEL selector = @selector(myMethod:setValue2:);

NSMethodSignature *signature = [MyObject instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];

NSString *str1 = @"someString";
NSString *str2 = @"someOtherString";

//The invocation object must retain its arguments
[str1 retain];
[str2 retain];

//Set the arguments
[invocation setTarget:targetInstance];
[invocation setArgument:&str1 atIndex:2];
[invocation setArgument:&str2 atIndex:3];

[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES];

MyObject est la classe qui myMethod:setValue2: est déclaré et mis en œuvre sur – instanceMethodSignatureForSelector: est une fonction de commodité déclaré sur NSObject qui retourne un NSMethodSignature objet pour vous, pour être transmis à l' NSInvocation.

Aussi, à noter, en setArgument:atIndex:, les indices pour les arguments passés à la méthode définie comme le sélecteur de commencer à l'index 2. À partir de la documentation:

Les Indices 0 et 1 indiquent le caché arguments de soi et _cmd, respectivement; vous devez régler ces valeurs directement avec le setTarget: et setSelector: méthodes. Utiliser les indices 2 et plus pour les arguments normalement transmis dans un message.

27voto

Matt Ball Points 4929

Pour scheduledTimerWithTimeInterval:, le sélecteur vous passez peut avoir qu'un seul argument. De plus, c'est un argument doit être un NSTimer * objet. En d'autres termes, le sélecteur doit prendre la forme suivante:

- (void)timerFireMethod:(NSTimer*)theTimer

Ce que vous pourriez faire est de stocker les arguments dans l' userInfo dictionnaire et appelez le sélecteur vous voulez à partir de la minuterie de rappel:

- (void)startMyTimer {
    /* ... Some stuff ... */
    [NSTimer scheduledTimerWithTimeInterval:0.1 
                                     target:self 
                                   selector:@selector(callMyMethod:) 
                                   userInfo:[NSDictionary dictionaryWithObjectsAndKeys:someValue, 
                       @"value1", someOtherValue, @"value2", nil] 
                                    repeats:YES];
}

- (void)callMyMethod:(NSTimer *)theTimer {
    NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];
    NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];
    [self myMethod:value1 setValue2:value2];
}

2voto

NSResponder Points 14459

Ressemble à un travail pour les blocs (en supposant que c'est ciblé pour Snow Leopard.)

-rjc

0voto

Grady Player Points 7823

les blocs semblent comme une réponse évidente maintenant... mais il y a un autre idiome qui était très courante dans le classique de l'exécution, les achards de vos arguments dans un seul objet:

 - (void)doMyMethod:(NSDictionary *)userInfo
 {
     [self myMethod: [userInfo objectForKey:@"value1"] setValue2: [userInfo objectForKey:@"value2"]];
 }
 - (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

maintenant, vous pouvez expédier à

[self performSelector:@selector(doMyMethod:) withObject:@{@"value1":@"value1",@"value2":@"value2"}];

-2voto

jbrennan Points 7307
@selector(myMethod:setValue2:)

Depuis le sélecteur de mode n'est pas seulement appelés myMethod mais au lieu myMethod:setValue2:.

Aussi (et je pourrais être hors de la base ici), je pense que, techniquement, vous pouvez supprimer les mots entre deux points, et donc également utiliser @selector(myMethod::) mais de ne pas me citer sur ce à moins que d'autres peuvent le confirmer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X