Y a-t-il un moyen de passer des arguments dans le sélecteur?
Exemple : J'ai cette méthode
- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{
}
et je dois appeler cette fonction à travers un sélecteur qui passe deux arguments.
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES];
Comment puis-je faire ceci?
Vous pouvez utiliser la méthode NSTimer
:
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
invocation:(NSInvocation *)invocation
repeats:(BOOL)repeats;
Au lieu de cela, étant donné qu'un objet NSInvocation
vous permettra de passer des arguments; Un objet NSInvocation
est, en tant que Docs Définir:
un message Objective-C a rendu statique, c'est-à-dire que c'est une action transformée en un objet.
Tout en créant un objet NSTimer
à l'aide d'un sélecteur nécessite 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 transmettez:
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];
Où MyObject
est la classe que myMethod:setValue2:
est déclaré et mis en œuvre sur - instanceMethodSignatureForSelector:
est une fonction de commodité déclarée sur NSObject
qui retourne un objet NSMethodSignature
pour vous, à transmettre à NSInvocation
.
Aussi, noter, avec setArgument:atIndex:
, les indices pour les arguments à transmettre à la méthode définie comme le sélecteur commencent à l'index 2. de la DOCS:
Les indices 0 et 1 indiquent les arguments cachés eux-mêmes et _cmd, respectivement; Vous devez définir ces valeurs directement avec le SetTarget: et SetSelector: méthodes. Utilisez les indices 2 et plus pour les arguments normalement passés dans un message.
Pour scheduledTimerWithTimeInterval:
, le sélecteur que vous passez ne peut avoir qu'un seul argument. En outre, son seul argument doit être un NSTimer *
objet. En d'autres termes, le sélecteur doit prendre le formulaire suivant:
- (void)timerFireMethod:(NSTimer*)theTimer
Ce que vous pouvez faire est de stocker les arguments du dictionnaire userInfo
et appelez le sélecteur souhaité à partir du rappel de la minuterie:
- (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];
}
Ressemble à un travail pour les blocs (en supposant que cela soit ciblé pour le léopard des neiges.)
-JCR
les blocs semblent une réponse évidente maintenant ... mais il y a une autre idiome très banale dans le runtime classique, cornichez 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"}];