0

I am showing a count down timer using UILabel and NSTimer -

-(void)a_Method
{
    [coolTimeLbl setNeedsDisplay];
    coolTime = 5;  // it is an int
    coolingTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(cooling) userInfo:nil repeats:YES];  // NSTimer
}

-(void)cooling
{
    if (coolTime>0) 
    {
        coolTime = coolTime-1;

        NSLog(@" coolTime----%@",coolTime);
        coolTimeLbl.text =[NSString stringWithFormat:@"%d",coolTime];
        NSLog(@" coolTimeLbl----%@",coolTimeLbl.text);
    }
    else
    {     
        [coolingTimer invalidate];
        coolingTimer = nil;
    }
}

The first time everything works fine and I am getting coolTimeLbl.text as - 4 3 2 1 0

But the second time when I call aMethod, coolTimeLbl is not getting updated properly - it is like 3 2 0 etc (some weird behavior)
However both NSLogs (coolTime & coolTimeLbl) print perfectly all the times and values.

Why does this happen? I tried many ways like NSNotification etc. Please help me to fix this.

Stonz2
  • 6,306
  • 4
  • 44
  • 64
  • is `a_Method` called on the main thread? – Stonz2 Aug 05 '14 at 19:10
  • I've replicated your code and do not have any issues. You're either calling `a_Method` from a background thread (which causes issues with updating the UI) or you're manipulating `coolTime` somewhere other than in your `cooling` method (which causes it to skip a number in the timer) – Stonz2 Aug 05 '14 at 19:18

2 Answers2

1

If you're calling a_Method more than once before coolingTimer invalidates itself, the timer will tick more than once.

You should add some boolean like ;

BOOL isTimerValid;

in a_Method,

if(!isTimerValid)
{     
    isTimerValid = YES;
    coolingTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(cooling) userInfo:nil repeats:YES];  // NSTimer
}

in cooling,

else
{
    isTimerValid = NO;
    ....
}
EDUsta
  • 1,932
  • 2
  • 21
  • 30
  • But I am not calling the method again before making the NSTimer invalidate. –  Aug 05 '14 at 19:14
  • Okay then, it is likely that there seems to be an external thing as Stonz said. – EDUsta Aug 05 '14 at 19:26
  • After further testing, I agree with EDUsta. You must be calling the method twice before invalidating (remember that it takes a full second AFTER the label changes to 0 before it gets invalidated). This makes one of your timers keep running in the background because... well, I'm not sure why, but it does. Look at the actual timestamps of the `NSLog` statements and you'll probably see that it's firing more than once per second. Build in EDUsta's `BOOL` and I'd wager that your problem would get fixed. – Stonz2 Aug 05 '14 at 19:28
  • And as for why it doesn't invalidate, see [this answer](http://stackoverflow.com/questions/18745175/nstimer-doesnt-stop-with-invalidate) – Stonz2 Aug 05 '14 at 19:31
  • If I am firing it more than once, then it should be caught twice on the break points. But it is not happening. –  Aug 05 '14 at 19:31
  • Put an `NSLog` statement in your `else{ invalidate }` statement to see if it keeps firing after your countdown completes. – Stonz2 Aug 05 '14 at 19:33
0

Had the same issue in one of my viewControllers and another one was working OK with same NSTimer code. Looked at about 20 SO threads to get it solved. No luck. In my case

myLabel.opaque = false

solved it. Don't ask me why.

guido
  • 2,792
  • 1
  • 21
  • 40