2016-06-01 1 views
0

Странная ситуация:NSTimer Нажмите кнопку «Start» Опять то не может «Стоп»

Если я снова и снова начал свой таймер, не останавливая его первым, он будет считать все более быстро. Думаю, это потому, что сейчас начинается несколько таймеров?

Однако, когда я, наконец, хочу остановить его, его нельзя остановить ... продолжайте навсегда.

(Может быть, для дизайна рассмотрения, следует отключить пользователей от повторного нажатия старт, но я задаюсь вопросом, что на самом деле за этим и почему таймер не может быть остановлен.)

- (IBAction)Start:(id)sender { 
    countInt = 0; 
    self.Time.text = [NSString stringWithFormat:@"%i", countInt]; 
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countTimer) userInfo:nil repeats:YES]; 
} 

- (IBAction)Stop:(id)sender { 
    [timer invalidate]; 
} 

- (void) countTimer { 
    countInt += 1; 
    self.Time.text = [NSString stringWithFormat:@"%i", countInt]; 
} 
@end 
+0

показать свой код, предположительно, вы не признаете недействительным, и вы также убиваете свою ссылку на таймер ... – Wain

+3

Отправьте код, а не фотографии! - Измените свой вопрос. – vadian

+0

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

ответ

2

Предполагая, что есть свойство timer

@property NSTimer *timer; 

самый надежный способ для запуска и остановки таймера только один раз, соответственно, заключается в создании двух методов.

- (void)startTimer 
{ 
    if (self.timer == nil) { 
     self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 
                 target:self 
                selector:@selector(countTimer) 
                userInfo:nil 
                repeats:YES]; 
    } 
} 

- (void)stopTimer 
{ 
    if (self.timer != nil) { 
     [self.timer invalidate]; 
     self.timer = nil; 
    } 
} 

Оба метода выполняют проверку, поэтому таймер не может быть перезапущен во время его запуска и наоборот.

Теперь просто вызовите методы в start/stop IBActions (имена должны начинаться с строчной буквы).

- (IBAction)Start:(id)sender { 
    countInt = 0; 
    self.Time.text = [NSString stringWithFormat:@"%i", countInt]; 
    [self startTimer]; 
} 

- (IBAction)Stop:(id)sender { 
    [self stopTimer]; 
} 

Выгода поджимает Start не имеет никакого эффекта, когда таймер уже запущен.

+0

Только мелочь: никакой проверки в '-stopTimer:' необходимо, потому что ничего не будет сделано, если это 'nil'. –

+0

На самом деле это правильно, но эффективнее ли отправлять ** два ** сообщения на нулевой указатель (одно сообщение и одно избыточное задание), а не делать ** один ** проверить? – vadian

+0

Ничего себе, я действительно не ожидаю проблемы с производительностью в методе действий из-за двух сообщений на nil против одного сообщения, а не на nil. (Тем не менее, они оптимизировали поведение сообщения для nil.) Это просто для краткости кода. –

0

Когда вы нажмете «начать» несколько раз, когда вы создаете несколько таймеров. Таким образом, вы получаете несколько таймеров, запускающих и выполняющих обратный вызов таймера. В этом обратном вызове таймера вы увеличиваете счетчики. Поскольку сейчас существует много таймеров, все они увеличивают ваш счетчик, поэтому объясняют быстрое увеличение счетчика.

Вы можете разрешить пользователю дважды нажать «Пуск», пока вы не можете определить, что произойдет, когда вы нажмете «Пуск», пока таймер уже идет. Но вам необходимо установить invalidate старый таймер перед созданием нового.

- (IBAction)Start:(id)sender { 
    ... 
    // Stop previous timer before creating a new timer. 
    if (timer != nil) { 
     [timer invalidate] 
    } 
    ... 
} 
+0

Спасибо! «Прекратить вызов» в начале запуска - лучший способ аннулировать старый таймер? –

+0

Это один из способов. Вы также можете вручную вызвать [timer invalidate]. Зависит от реальной реализации метода Stop. –

3

Простое решение заключается в вызове stop в начале метода start.

Обратите внимание, что в stop вы должны также установить timer = nil;

+0

Прохладный. Почему я должен установить таймер на «nil»? Должен ли я всегда устанавливать объекты в ноль, когда я их останавливал? –

+1

Вы хотите, чтобы 'timer' был установлен на' nil' после его недействительности, иначе вы можете снова попытаться ссылаться на недействительный указатель таймера. Установив его на «nil», вы будете в безопасности от этой проблемы. – rmaddy

Смежные вопросы