Comment passer des arguments lorsque la fonction d'appel avec minuterie dans c objectif

StackOverflow https://stackoverflow.com/questions/1527175

  •  20-09-2019
  •  | 
  •  

Question

-(void)setX:(int)x andY:(int)y andObject:(Sprite*)obj
{
    [obj setPosition:CGPointMake(x,y)];
}

Maintenant, je veux appeler méthode ci-dessus, en utilisant la minuterie suivante.

[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector() userInfo:nil repeats:NO];

Que mettre ici?

Comment passer des arguments? (Selon ma connaissance - sélecteur spécifie que la méthode d'invoquer)

Était-ce utile?

La solution 3

Copié d'une réponse par Matt Boule :

    - (void)startMyTimer {
        /* ... Some stuff ... */
        NSDictionary *userDict;
        userDict = [NSDictionary dictionaryWithObjectsAndKeys:someValue,
                                                              @"value1",
                                                              someOtherValue,
                                                              @"value2", nil];

        [NSTimer scheduledTimerWithTimeInterval:0.1
                                         target:self
                                       selector:@selector(callMyMethod:)
                                       userInfo:userDict
                                        repeats:YES];
}
    - (void)callMyMethod:(NSTimer *)theTimer {
        NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];
        NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];
        [self myMethod:value1 setValue2:value2];
    }

Autres conseils

Vous devez utiliser +[NSTimer scheduledTimerWithTimeInterval:invocation:repeats:] à la place. Par défaut, le sélecteur utilisé pour déclencher une minuterie prend un paramètre. Si vous avez besoin d'autre chose que cela, vous devez créer un

Si vous avez un ensemble assez complexe d'arguments que vous souhaitez utiliser pour invoquer la méthode, je recommande la capture des arguments en quelque chose qui contient une configuration et peut faire quoi que ce soit que les besoins basés sur cette faisant, la configuration ...

Quelque chose avec une interface comme ceci:

PositionSetter.h:

@interface  PositionSetter : NSObject
{
    NSInteger x;
    NSInteger y;
    Sprite *target;
}

+ positionSetterWithX: (NSInteger) xPos y: (NSInteger) yPos sprite: (Sprite *) aSprite; 

- (void) applyPosition;
@end

PositionSetter.m:

@interface PositionSetter()
@property(readwrite, nonatomic) NSInteger x;
@property(readwrite, nonatomic) NSInteger y;
@property(readwrite, nonatomic, retain) Sprite *target;
@end

@implementation PositionSetter
@synthesize x, y, target;

+ positionSetterWithX: (NSInteger) xPos y: (NSInteger) yPos sprite: (Sprite *) aSprite; 
{
    PositionSetter *positionSetter = [PositionSetter new];
    positionSetter.x = xPos;
    positionSetter.y = yPos;
    positionSetter.target = aSprite;
    return [positionSetter autorelease];
}

- (void) applyPosition;
{
    [self.target setPosition:CGPointMake(self.x,self.y)];
}
@end

L'utilisation est assez simple:

positionSetter = [PositionSetter positionSetterWithX: 42 y: 21 sprite: mySprite];
[positionSetter performSelector: @selector(applyPosition) withObject: nil afterDelay: 1.0];

Alors qu'un peu plus de code, la mise en œuvre résultant sera assez rapide - sans doute plus vite que NSInvocation, mais assez vite pour être hors de propos étant donné que ça va dessin cause - et un diable de beaucoup plus souple. Je pouvais facilement voir refactorisation ci-dessus dans la conduite, par exemple, CoreAnimation.

Si vous utilisez une minuterie cible action, vous ne pouvez pas avoir la minuterie appeler directement une méthode arbitraire. L'action d'un minuteur doit avoir une signature très spécifique. Vous pouvez transmettre des données supplémentaires dans le dictionnaire userinfo et ont la méthode que vous voulez finalement l'appel d'action de la minuterie, ou vous pouvez utiliser le formulaire d'appel comme Dave dit. Personnellement, je fais habituellement le premier, parce que je trouve NSInvocations d'être ennuyeux et une mise en place peut effectivement prendre plus de code que d'écrire juste une méthode intermédiaire.

Vous pouvez passer un NSDictionary *, ou un autre objet, comme userInfo et de mettre les arguments à cela.

Comme alternative à NSTimer, sur iOS 4.0+ et 10.6+, vous pouvez utiliser Grand Central Dispatch et les sources d'expédition pour le faire en utilisant un bloc. Apple a le code suivant pour cela dans leur Concurrency Guide de programmation :

dispatch_source_t CreateDispatchTimer(uint64_t interval, uint64_t leeway, dispatch_queue_t queue, dispatch_block_t block)
{
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    if (timer)
    {
        dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
        dispatch_source_set_event_handler(timer, block);
        dispatch_resume(timer);
    }
    return timer;
}

Vous pouvez ensuite mettre en place un événement d'horloge d'une seconde en utilisant le code comme suit:

dispatch_source_t newTimer = CreateDispatchTimer(1ull * NSEC_PER_SEC, (1ull * NSEC_PER_SEC) / 10, dispatch_get_main_queue(), ^{
    [self setX:someValue andY:otherValue andObject:obj];
});

tant que vous stockez et relâchez votre minuterie lorsque vous avez terminé. Cela peut même vous permettre de déclencher une minuterie pour exécuter des éléments sur un thread d'arrière en utilisant une file d'attente simultanée au lieu de la file d'attente principale utilisée ci-dessus.

Cela permet d'éviter la nécessité de la boxe et des arguments unboxing.

Créer un dictionnaire avec ces arguments et passer ce dictionnaire avec minuterie userinfo. Cela permettra de résoudre votre problème

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top