views:

954

answers:

2

I have a -(void)save method that is called when a user clicks a navigation bar button. In that method is the following NSTimer:

[NSTimer scheduledTimerWithTimeInterval:.25f target:self selector:@selector(flashBackgroundRed) userInfo: nil repeats: flashRepeat];

The timer repeats 4 times since the flashBackgroundRed keeps a count and sets flashRepeat to NO after 4 hits. All works well the first time a user clicks to save. But if the user keeps hitting save with incorrect data, I keep them on the current view. For some reason, flashes get increasing faster. As if each one is 25% of the previous one's interval. I'm not retaining this timer. It only lives in the save method.

If the user clicks the cancel button, viewB (one with NSTimer) is popped and viewA displays. Going from viewA back to viewB seems to reset the timer invterval. But the increasingly fast flashes cycle starts again. Any ideas?

+1  A: 

NSTimer is retained by the run loop as long as it is scheduled.

It sounds like the problem is that you keep creating equivalent repeating timers at slightly different times, so they visually mesh together into one effect with a different frequency than you want. Try storing a reference to the timer and invalidating it when you're going to create a new one.

Chuck
Yes - I've declared a class level reference and invalidate before running the above code. Works fine.
4thSpace
+1  A: 

It sounds like you are scheduling more timers than you intend to.

Once scheduled, timers are retained until invalidated. Repeating timers must be manually invalidated.

The repeats argument specifies if the timer will repeat. You can't specify how many times a timer should repeat, only whether or not it will.

Also, the method signature for your selector is wrong. It should look like

-(void)timerFireMethod:(NSTimer*)theTimer

In your timer callback you can determine if you want the timer to continue repeating or not; if not, call [timer invalidate].

sbooth
How do you use parameters with a selector?
4thSpace
It would look like [NSTimer scheduledTimerWithTimeInterval:.25f target:self selector:@selector(flashBackgroundRed:) userInfo: nil repeats: flashRepeat];
sbooth
Why doesn't it like this: selector:@selector(flashBackground::[UIColor redColor])...for...-(void) flashBackground:(NSTimer*) theTimer attentionColor:(UIColor*)theColor{...}
4thSpace
userInfo takes any object and that is where the selector parameters go. For example, if I need multiple parameters, I'll pass an array to userInfo and take it out in my selector target as (NSMutableArray *)[theTimer userInfo].
4thSpace
I think you're a bit confused about the way this selector works. The selector you pass when creating a timer is a callback, called when the timer fired. The timer which fired is the parameter passed to the selector, and as you said you can store whatever you need in that timer's userinfo.
sbooth
Ok. I agree with everything you said except the first statement, which is confusing.
4thSpace
I just realized there is a typo in my comment- it should say "when the timer FIRES", not "when the timer fired". Sorry about that!
sbooth