0

I've got a NSTimer and a label which shows the seconds counting down.

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

}

So when the time is 0, the timer should stop and the ResultViewController should load, but when I do it the timer still counts down into negative numbers and nothing happens.

Is there anybody who can help me?

Thank you :)

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Leon
  • 417
  • 3
  • 11
  • 24

6 Answers6

2

0.01 doesn't have an exact floating point binary representation, so your float will never get to exactly zero. Use <= instead of == in your comparison.

tgdavies
  • 10,307
  • 4
  • 35
  • 40
0

Floating point arithmetic isn't "precise" oftentimes (see http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems ) . Change the check to if (currentTime <= 0.0) and you'll be fine.

Jonas Bötel
  • 4,452
  • 1
  • 19
  • 28
0

Try something like this:

if(currentTime <= 0.0)
     ...

What you're suffering from is floating point drift. It's a well known phenomenon.

jer
  • 20,094
  • 5
  • 45
  • 69
0

Not all numbers can be stored accurately with floating point variables. Just as 1/3 can't be represented with finite digits in base 10, 1/10 can't be represented with finite digits in base 2. What you end up with is rounded to 0.10000000000000001 or close. So when you subtract 0.1 from that, you don't quite get 0.

The most robust solution to this is to store your time as milliseconds in an integer and divide it when you want to update the label. Don't bother going back and forth from the label to the number either. The canonical storage of the number should be as a number. The label is just to display it.

Edit:

For everybody recommending that he just change to <= instead - this is just a hack that barely scrapes by. Floating point representation of 0.1 is often 0.10000000000000001. What happens when you subtract 0.1 from that? It's still above 0. The conditional only triggers when it reaches almost -0.1, which isn't expected behaviour from the app. This is a bad solution.

Jim
  • 72,985
  • 14
  • 101
  • 108
0

ResultViewController should just alloc init instead of the alloc initWithNibName set to nil.

current time comparison should be put as if (currentTime <= (float)0.0) or similar (Reason for it refer to:this thread)

Community
  • 1
  • 1
Seyther
  • 652
  • 4
  • 6
-1

Better not compare against an int. Try to do this:

if (currentTime == 0.0) {
SteAp
  • 11,853
  • 10
  • 53
  • 88