8

我有一个NSTimer以 3 秒的间隔触发以减小值的方法。当我执行增加该值的操作时,我想重新启动计时器以从该点开始计数 3 秒。

例如,如果我增加值并且计时器将在 1 秒内触发,我想更改它并让计时器在 3 秒内触发。我可以使计时器无效并重新创建它吗?或者我可以setFireDate:使用当前日期并添加 3 秒的间隔来执行此操作吗?

4

5 回答 5

7

是的,您可以使其无效。并再次创建它。

您还可以使用:

- (void) myTimedTask {
    // other stuff this task needs to do

    // change the variable varyingDelay to be 1s or 3s or...  This can be an instance variable or global that is changed by other parts of your app
    // weStillWantTimer is also a similar variable that your app uses to stop this recurring task

if (weStillWantTimer)
       [self performSelector:@selector(myTimedTask:) withObject:gameColor afterDelay:varyingDelay];

 }

您调用 myTimedTask 来启动循环任务。启动后,您可以使用 varyingDelay 更改延迟或使用 weStillWantTimer 停止它。

于 2009-10-17T17:41:20.240 回答
4

我做了一些测试,结果证明重置 fireDate 比无效和重新创建计时器快四倍。首先,我创建一个调用方法 doNothing 的计时器:

if (!testTimer) {
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                      target:self
                                                    selector:@selector(doNothing:)
                                                    userInfo:nil
                                                     repeats:NO];
    testTimer   = timer;
}

这是测试代码:

- (void) testInvalidatingTimer {
    for (int n = 0; n < 10000; n++) {
        [testTimer invalidate];
        testTimer = nil;

        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                          target:self
                                                        selector:@selector(doNothing:)
                                                        userInfo:nil
                                                         repeats:NO];
        testTimer   = timer;
    }
}

- (void) testResettingTimer {
    for (int n = 0; n < 10000; n++) {
        if ([testTimer isValid]) {
            testTimer.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0];
        }
    }
}

在 iPad Air 上运行该程序会产生 0.198173 秒的无效定时器和 0.044207 秒的重置定时器。如果性能是您的目标,我建议重置 fireDate。它的编码工作量也少了很多。

于 2015-06-10T08:55:10.450 回答
1

使计时器无效并重新创建它。但是,请确保您不会使计时器无效释放,除非您确定需要这样做,因为运行循环会保留计时器,直到它们无效,然后自行释放它们。

在我看来,将 -performSelector 代码与计时器代码混合会导致目标方法的多次执行,所以我会远离它。

于 2009-10-17T17:50:45.320 回答
1

是的,使计时器无效并重新创建将起作用。如果您不增加价值,这基本上就是您想要做的:重置并重新开始。

于 2009-10-17T17:56:17.463 回答
1

文档提到更改触发日期相对昂贵,这setFireDate:表明最好销毁并重新创建计时器,除非您经常这样。然而,为了争论,我不久前就提出了这个类别。我更喜欢这个,因为它封装了日期调整行为;计时器本身处理它,而不是它的所有者/控制器。不过,我没有这方面的任何性能数据。

@implementation NSTimer (WSSAdjustingFireDate)

- (void)WSSFireAdjustingFireDate
{
    [self fire];

    [self WSSSkipNextFireAdjustingFireDate];
}

- (void)WSSSkipNextFireAdjustingFireDate
{
    CFRunLoopTimerRef cfSelf = (__bridge CFRunLoopTimerRef)self;
    CFTimeInterval delay = CFRunLoopTimerGetInterval(cfSelf);
    CFRunLoopTimerSetNextFireDate(cfSelf, CFAbsoluteTimeGetCurrent() + delay);
}

@end

我使用 Core Foundation 函数只是为了避免创建NSDate. 过早优化?请把盐递过去。

于 2013-02-27T01:52:06.933 回答