2009-06-23 4 views
13

Я пытаюсь создать таймер обратного отсчета, который принимает обратный отсчет, IBOutlet подключен к текстовому полю, от 60 секунд до 0. Я не уверен,Таймер обратного отсчета

А. Как ограничить число повторений до 60 и

B. Как уменьшает отсчет в 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]; 
} 

ответ

19

Вы находитесь на правильном пути, до сих пор.

Вставлять с кодом у вас уже есть, вот как advanceTimer метод должен выглядеть, чтобы сделать его работу:

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

редактировать: Чтобы сделать все это более объектно-ориентированным, и, чтобы избежать преобразования из строк в числа и обратно каждый раз, я бы вместо того, чтобы сделать что-то вроде этого:

// 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 

И, если вы можете использовать привязки, можно просто связать текстовое поле intValue к counter собственности Controller. Это позволит вам устранить IBOutlet в интерфейсе класса и строку setIntegerValue: в advanceTimer.

обновление: Удалено код, который дважды добавляет таймер в цикл запуска. Спасибо Николаю Рухе и ншмидту за то, что заметили эту ошибку.

обновление: Используется метод setIntegerValue для упрощения кода в соответствии с nschmidt.

редактировать: опечатки в определении (аннулируется) advanceTimer: таймер (NSTimer *) ... вызвала раздражающий «непризнанный селектор послал к экземпляру» исключению

+0

Обратный отсчет времени повторяется дважды, что неверно. –

+0

@Nikolai Ruhe: Спасибо, что указали это. Я удалил неправильный код из своих примеров. –

+0

Я предполагаю, что setIntegerValue более эффективен, чем [NSString stringWithFormat:], поэтому я бы не сделал эту «оптимизацию». Тем более, что это не помогает ясности кода. – nschmidt

6

Вы можете добавить экземпляр переменной Int _timerValue для удерживания таймера, а затем выполните следующее. Также обратите внимание, что созданный вами NSTimer уже запланирован в текущем цикле выполнения.

- (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]; 
} 
Смежные вопросы