将NSTimer的fireDate的时间加倍

时间:2014-03-08 22:37:33

标签: ios objective-c cocoa-touch nstimer

我正在使用NSTimer,在某些情况下,我希望在方法NSTimer调用被调用之前加倍。

基本上:如果我将它设置为每0.5秒调用一次,我偶尔会延迟它,以便在下次调用它之前等待1.0秒(加倍时间)。

然而,我在实现这个方面遇到了很多困难。这是我最初的尝试:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [NSTimer scheduledTimerWithTimeInterval:0.5 
                                     target:self 
                                   selector:@selector(timerMethod:) 
                                   userInfo:nil 
                                    repeats:YES];
}

- (void)timerMethod:(NSTimer *)timer {
    static int variable = 1;

    switch (variable) {
        case 1:
            self.stopLightLabel.textColor = [UIColor redColor];
            break;
        case 2:
            self.stopLightLabel.textColor = [UIColor orangeColor];
            break;
        case 3:
            self.stopLightLabel.textColor = [UIColor yellowColor];
            break;
        case 4: // Stop for twice as long here
            self.stopLightLabel.textColor = [UIColor greenColor];

            NSTimeInterval timeBetweenNowAndFireDate = [timer.fireDate timeIntervalSinceNow];

            // Create a new date that is twice as far in the future in order to give a long pause
            timer.fireDate = [NSDate dateWithTimeIntervalSinceNow:(timeBetweenNowAndFireDate * 2)];

            break;
        case 5:
            self.stopLightLabel.textColor = [UIColor blueColor];
            break;
        case 6:
            self.stopLightLabel.textColor = [UIColor purpleColor];
            break;
        default:
            break;
    }

    variable++;
}

我尝试在现在和计时器启动之间获得时间。在上面的示例中,这应该是0.5。然后我将fireDate设置为一个新值,该值是之前的两倍。

然而,这不起作用。

如果没有条件,计时器正常工作,但显然不会在某种情况下延迟(对于那种情况,它会获得与其他所有时间相同的时间)。

使用条件,它甚至会显示更短!事实上,直到我将它乘以大约400而不是2来它才会变得更长!

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

您调用代码来修改timerFired方法中的fireDate。那太早了。 fireDate是计时器DID在那里开火的日期..它还没有更新。

一个简单的修复:将其包装在一个异步调度中。允许计时器返回并在尝试修改它之前更新其fireDate:

固定代码:

- (void)timerMethod:(NSTimer *)timer {
    static int variable = 1;

    dispatch_async(dispatch_get_main_queue(), ^{
        [self afterTimerFired:timer];
    }
 }

- (void)afterTimerFired:(NSTimer *)timer {
    static int variable = 1;        
        switch (variable) {

            case 4: // Stop for twice as long here
                self.stopLightLabel.textColor = [UIColor greenColor];
                ...
                NSTimeInterval timeBetweenNowAndFireDate = [timer.fireDate timeIntervalSinceNow];
                NSLog(@"%f", timeBetweenNowAndFireDate);
                // Create a new date that is twice as far in the future in order to give a long pause
                timer.fireDate = [NSDate dateWithTimeIntervalSinceNow:(timeBetweenNowAndFireDate * 2)];
                ...

OR

不要发送异步和make 如果可能的话fireDate = [NSDate dateWithTimeIntervalSinceNow:fire.timeInterval*2]可能更干净

答案 1 :(得分:1)

我很确定你无法改变正在运行的计时器的fireDate。 (这是错误的。请参阅下面的编辑。)

另一张海报Paul.s,我的想法与此相同。如果你有一个每0.5秒触发一次的计时器,则将BOOL skipThisInterval实例变量添加到作为计时器目标的对象。

然后,在你的timer方法中,如果skipThisInterval为true,只需重置skipThisinterval = FALS E并返回而不做任何其他操作。这样,计时器将在另一个间隔过去后再次触发,然后像以前一样继续运行。

如果失败了,你必须使正在运行的计时器无效,创建一个新的计时器,它将在你想要的结束时间触发一次,然后在计时器调用的方法中,创建一个新的重复计时器,然后重新启动旧的间隔。

编辑:我错了。您可以更改“飞行中”计时器的开火日期。 (感谢Josh Caswell纠正我。)

即便如此,如果你只是想让你的计时器只是跳过它的下一次射击并继续前进,只需在方法中调用逻辑,定时器调用以跳过下一次射击似乎比调整fireDate更简单,更清晰(并且文档说改变开火日期相对昂贵。)