Остановите NSTimer, когда float равен 0 - PullRequest
0 голосов
/ 07 марта 2011

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

-(void)start {

myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showActivity) userInfo:nil repeats:YES];

}

- (IBAction) stop {

[myTimer invalidate];

}

- (void) showActivity {

currentTime = [timeLabel.text floatValue];
currentTime -= 0.01;
timeLabel.text = [NSString stringWithFormat:@"%.2f", currentTime];  

if (currentTime == 0) {

    [self stop];

    ResultViewController *screen = [[ResultViewController alloc] initWithNibName:nil bundle:nil];
    screen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self presentModalViewController:screen animated:YES];
    [screen release];
}

}

- (void)viewDidLoad {
[super viewDidLoad];
timeLabel.text = @"60.0";
[self start];

}

Поэтому, когда время равно 0, таймер должен остановитьсяи ResultViewController должен загрузиться, но когда я делаю это, таймер продолжает отсчитывать отрицательные числа, и ничего не происходит.

Кто-нибудь может мне помочь?

Спасибо:)

Ответы [ 6 ]

2 голосов
/ 07 марта 2011

0.01 не имеет точного двоичного представления с плавающей запятой, поэтому ваше значение с плавающей запятой никогда не достигнет точно нулевого значения. Используйте <= вместо == в своем сравнении. </p>

0 голосов
/ 07 марта 2011

ResultViewController должен просто выделить init вместо alloc initWithNibName, установленной в nil.

текущее сравнение времени должно быть указано как if (currentTime <= (float)0.0) или аналогичное (Причина этого указана: эта тема )

0 голосов
/ 07 марта 2011

Не все числа могут быть точно сохранены с помощью переменных с плавающей запятой.Точно так же, как 1/3 нельзя представить с помощью конечных цифр в базе 10, 1/10 нельзя представить с помощью конечных цифр в базе 2. То, что вы в итоге получите, округляется до 0,10000000000000001 или близко.Поэтому, когда вы вычитаете 0,1 из этого, вы не совсем получаете 0.

Самое надежное решение для этого - хранить ваше время в виде миллисекунд в целом числе и делить его, когда вы хотите обновить метку.Не беспокойтесь о том, чтобы переходить от метки к номеру.Каноническое хранение номера должно быть как число.Ярлык предназначен только для его отображения.

Редактировать:

Для всех, кто рекомендует просто заменить его на <= - это всего лишь хак, который едва ли,Представление с плавающей точкой 0,1 часто 0,10000000000000001.Что происходит, когда вы вычитаете 0,1 из этого?Это все еще выше 0. Условное срабатывает только тогда, когда оно достигает почти -0.1, что не ожидается поведение от приложения.Это плохое решение.

0 голосов
/ 07 марта 2011

Попробуйте что-то вроде этого:

if(currentTime <= 0.0)
     ...

То, от чего вы страдаете, это дрейф с плавающей точкой. Это хорошо известное явление.

0 голосов
/ 07 марта 2011

Арифметика с плавающей точкой часто не является "точной" (см. http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems).Измените чек на if (currentTime <= 0.0), и все будет в порядке.

0 голосов
/ 07 марта 2011

Лучше не сравнивать с инт. Попробуйте сделать это:

if (currentTime == 0.0) {
...