2011-03-02 2 views
6

J'ai une minuterie appeler une méthode, mais cette méthode prend un paramether:Comment passer un argument à une méthode appelée dans un NSTimer

theTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(timer) userInfo:nil repeats:YES]; 

devrait être

theTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(timer:game) userInfo:nil repeats:YES]; 

maintenant cette syntaxe n » Cela semble être juste. J'ai essayé avec NSInvocation mais j'ai eu quelques problèmes:

timerInvocation = [NSInvocation invocationWithMethodSignature: 
     [self methodSignatureForSelector:@selector(timer:game)]]; 

theTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval 
     invocation:timerInvocation 
     repeats:YES]; 

Comment devrais-je utiliser l'Invocation?

Répondre

11

Compte tenu de cette définition:

- (void)timerFired:(NSTimer *)timer 
{ 
    ... 
} 

Vous devez alors utiliser @selector(timerFired:) (qui est le nom de la méthode sans espaces ni noms d'argument, mais y compris les deux points). L'objet que vous souhaitez passer est passé par la userInfo: partie (game?):

theTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval 
              target:self 
              selector:@selector(timerFired:) 
             userInfo:game 
              repeats:YES]; 

Dans votre méthode de minuterie, vous pouvez accéder à cet objet via la méthode de l'objet minuterie userInfo:

- (void)timerFired:(NSTimer *)timer 
{ 
    Game *game = [timer userInfo]; 
    ... 
} 
2

Vous peut passer NSDictionary avec des objets nommés (comme myParamName => myObject) par le paramètre userInfo comme celui-ci

theTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval 
              target:self 
              selector:@selector(timer:) 
              userInfo:@{@"myParamName" : myObject} 
              repeats:YES]; 

Puis, en timer: méthode:

- (void)timer:(NSTimer *)timer { 
    id myObject = timer.userInfo[@"myParamName"]; 
    ... 
} 
+0

Si vous devez passer plusieurs objets, c'est le chemin à parcourir. Mais si c'est juste un seul objet, vous n'avez pas besoin de l'encapsuler dans un dictionnaire. – DarkDust

+0

True. Je viens de voir les notifications utiliser les dictionnaires userInfo afin de garder la cohérence. – Eimantas

5

Comme le souligne @DarkDust sur, NSTimer attend sa méthode cible d'avoir une signature particulière. Si, pour une raison quelconque, vous ne pouvez pas vous y conformer, vous pouvez utiliser un NSInvocation comme vous le suggérez, mais dans ce cas vous devez l'initialiser complètement avec le sélecteur, la cible et les arguments. Par exemple:

timerInvocation = [NSInvocation invocationWithMethodSignature: 
        [self methodSignatureForSelector:@selector(methodWithArg1:and2:)]]; 

// configure invocation 
[timerInvocation setSelector:@selector(methodWithArg1:and2:)]; 
[timerInvocation setTarget:self]; 
[timerInvocation setArgument:&arg1 atIndex:2]; // argument indexing is offset by 2 hidden args 
[timerInvocation setArgument:&arg2 atIndex:3]; 

theTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval 
             invocation:timerInvocation 
              repeats:YES]; 

Appel invocationWithMethodSignature lui-même ne fait pas tout cela, il crée simplement un objet qui peut être rempli de la bonne manière.

Questions connexes