Reputation: 355
I do understand that it's my problem but not the problem of NSTimer but I would be really grateful if anyone could help me. In my project I need to call this method every 0.5 seconds for 2 objects. The problem is that the timer fires at different moments of time. It may immediately fire 3 or 5 times (together for for both objects) and then it'll do the same after 0.5 seconds and again, and again.
-(void) blinkLamp{
switch (currentState) {
case blinkingGreen:
NSLog(@"blink green lamp");
self.greenLamp = !self.greenLamp;
self.colorState[0] = [NSNumber numberWithBool:greenLamp];
self.rndValuesChanged = rand();
break;
case blinkingYellow:
NSLog(@"blink yellow lamp");
self.yellowLamp = !self.yellowLamp;
self.colorState[1] = [NSNumber numberWithBool:yellowLamp];
self.rndValuesChanged = rand();
break;
default:
break;
}
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkLamp) userInfo:nil repeats:NO];
}
This method is called once in the SetState method.
-(void) setState:(State)newState{
currentState = newState;
switch (newState) {
case green:
self.greenLamp = YES;
self.yellowLamp = NO;
self.redLamp = NO;
break;
case yellow:
self.greenLamp = NO;
self.yellowLamp = YES;
self.redLamp = NO;
break;
case red:
self.greenLamp = NO;
self.yellowLamp = NO;
self.redLamp = YES;
break;
case redYellow:
self.greenLamp = NO;
self.yellowLamp = YES;
self.redLamp = YES;
break;
case off:
self.greenLamp = NO;
self.yellowLamp = NO;
self.redLamp = NO;
break;
case blinkingGreen:
self.greenLamp = YES;
self.yellowLamp = NO;
self.redLamp = NO;
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkLamp) userInfo:nil repeats:NO];
break;
case blinkingYellow:{
self.greenLamp = NO;
self.yellowLamp = YES;
self.redLamp = NO;
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkLamp) userInfo:nil repeats:NO];
//[self blinkLamp];
break;}
default:
NSLog(@"This mode is not allowed for VehicleTL");
break;}
NSLog(@"G - %d Y - %d R - %d", self.greenLamp, self.yellowLamp, self.redLamp);
self.colorState[0] = [NSNumber numberWithBool:greenLamp];
self.colorState[1] = [NSNumber numberWithBool:yellowLamp];
self.colorState[2] = [NSNumber numberWithBool:redLamp];
self.rndValuesChanged = rand();
}
Upvotes: 0
Views: 162
Reputation: 9731
You are failing to track existing timers and are, instead, creating multiple timers, which is why you are getting them firing multiple times.
Use instance variables, and only create a timer if it's currently invalid:
case blinkingGreen:
self.greenLamp = YES;
self.yellowLamp = NO;
self.redLamp = NO;
[self createBlinkingTimer];
break;
case blinkingYellow:{
self.greenLamp = NO;
self.yellowLamp = YES;
self.redLamp = NO;
[self createBlinkingTimer];
//[self blinkLamp];
...
- (void)createBlinkingTimer
{
if (!self.blinkingTimer.isValid)
self.blinkingTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkLamp) userInfo:nil repeats:NO];
}
Upvotes: 2
Reputation: 38259
Mistake done here scheduled timer twice which will lead to calling of same method at different time which is you don't want it;
I would prefer here to use performSelector:withObject:afterDelay: instead of NSTimer
Make changes in setState: method
Note remove line : [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkLamp) userInfo:nil repeats:NO];
(void) setState:(State)newState
{
//.............
//.............
switch (newState) {
//...............
}
//The method should be called once only
if(self.greenLamp || self.yellowLamp)
[self performSelector:@selector(blinkLamp) withObject:nil afterDelay:0.5];
//.............
}
Make changes in blinkLamp: method
Note replace line : [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkLamp) userInfo:nil repeats:NO];
With : [self performSelector:@selector(blinkLamp) withObject:nil afterDelay:0.5]
;
Upvotes: 2