Таймер обратного отсчета - PullRequest
13 голосов
/ 23 июня 2009

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

A. Как ограничить повторы до 60 и

B. Как уменьшить отсчет времени заранее: время:

- (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];
}

Ответы [ 2 ]

19 голосов
/ 23 июня 2009

Пока вы на правильном пути.

Придерживаясь кода, который у вас уже есть, вот как должен выглядеть 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.

edit: Опечатка в определении (void) advanceTimer: (NSTimer *) timer ... вызвала раздражающее исключение "нераспознанный селектор, отправленный экземпляру"

6 голосов
/ 23 июня 2009

Вы можете добавить переменную экземпляра 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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...