2009-06-23 6 views
13

Je suis en train de créer un compte à rebours qui prend le compte à rebours, un IBOutlet connecté à un champ de texte, de 60 secondes à 0. Je ne sais pasCompte à rebours

A. Comment limiter les répétitions à 60 et

B. Comment diminuer le compte à rebours à advanceTimer:

- (IBAction)startCountdown:(id)sender 
{ 
    NSTimer *countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self  selector:@selector(advanceTimer:) userInfo:nil repeats:YES]; 
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
    [runLoop addTimer:countdownTimer forMode:NSDefaultRunLoopMode]; 
} 

- (void)advanceTimer:(NSTimer *)timer 
{ 
    [countdown setIntegerValue:59]; 
} 

Répondre

19

Vous êtes sur la bonne voie jusqu'à présent.

Tirer avec le code que vous avez déjà, voici comment la méthode advanceTimer devrait chercher à le faire fonctionner:

- (void)advanceTimer:(NSTimer *)timer 
{ 
    [countdown setIntegerValue:([countdown integerValue] - 1)]; 
    if ([countdown integerValue] == 0) 
    { 
     // code to stop the timer 
    } 
} 

modifier: Pour rendre plus orienté objet toute la chose, et d'éviter la conversion de chaînes en nombres et en arrière chaque fois, je place quelque chose comme ça:

// Controller.h: 
@interface Controller 
{ 
    int counter; 
    IBOutlet NSTextField * countdownField; 
} 
@property (assign) int counter; 
- (IBAction)startCountdown:(id)sender; 
@end 

// Controller.m: 
@implementation Controller 

- (IBAction)startCountdown:(id)sender 
{ 
    counter = 60; 

    NSTimer *countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1 
             target:self 
             selector:@selector(advanceTimer:) 
             userInfo:nil 
             repeats:YES]; 
} 

- (void)advanceTimer:(NSTimer *)timer 
{ 
    [self setCounter:(counter -1)]; 
    [countdownField setIntegerValue:counter]; 
    if (counter <= 0) { [timer invalidate]; } 
} 

@end 

Et, si vous pouvez utiliser des raccourcis, vous pouvez simplement lier le champ de texte intValue à la propriété counter du Controller. Cela vous permettra d'éliminer le IBOutlet dans l'interface de classe, et la ligne setIntegerValue: dans advanceTimer.

mise à jour: Suppression du code qui ajoute deux fois la minuterie à la boucle d'exécution. Merci à Nikolai Ruhe et à nschmidt d'avoir remarqué cette erreur.

mise à jour: Utilisé la méthode setIntegerValue pour simplifier le code, conformément à nschmidt.

modifier: Typo dans la définition de (void) advanceTimer: (NSTimer *) minuterie ... causé ennuyeux 'sélecteur non reconnu envoyé à l'instance' exception

+0

Le countdownTimer est ajouté deux fois à la boucle d'exécution, ce qui est incorrect. –

+0

@Nikolai Ruhe: Merci de l'avoir signalé. J'ai supprimé le code incorrect de mes exemples. –

+0

Je suppose que setIntegerValue est plus efficace que [NSString stringWithFormat:], donc je n'aurais pas fait cette "optimisation". Surtout que cela n'aide pas la clarté du code. – nschmidt

6

Vous pouvez ajouter une _timerValue variables instance int pour maintenir la valeur de la minuterie, puis procédez comme suit. Notez également que le NSTimer que vous créez est déjà planifié sur la boucle d'exécution en cours.

- (IBAction)startCountdown:(id)sender 
{ 
    _timerValue = 60; 
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer:) userInfo:nil repeats:NO]; 
} 

- (void)advanceTimer:(NSTimer *)timer 
{ 
    --_timerValue; 
    if(self.timerValue != 0) 
     [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(advanceTimer:) userInfo:nil repeats:NO]; 

    [countdown setIntegerValue:_timerValue]; 
}