重置一个NSTimer的发射时间是从现在开始,而不是最后的火(Reset an NSTimer

2019-08-19 17:41发布

我有一个NSTimer与3秒的时间间隔触发以减小的值。 当我这样做会增加值的行动,我要重新启动计时器从该点计数3秒。

例如,如果我增加1秒值和计时器将大火,我想改变这种状况,使计时器火灾在3秒内代替。 我可以无效计时器并重新创建它? 或者,我能和做setFireDate:使用当前的日期和加入的3秒的时间间隔?

Answer 1:

是的,你可以使它无效。 然后再重新创建。

你也可以使用:

- (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停止。



Answer 2:

我做了一个小测试,事实证明,重置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上的空气产生0.198173 S表示invalidatingTimer和0.044207 S代表resettingTimer。 如果性能是你的目标,我建议重置fireDate。 这也是相当少一点的编码工作。



Answer 3:

无效计时器并重新创建它。 但是,请确保你没有失效释放计时器,除非你确信你需要自运行循环保留计时器,直到它们无效,然后将其释放本身。

在我看来,混合-performSelector代码计时器代码导致的目标方法执行多次,所以我就留下来从远。



Answer 4:

是的,无效并重新创建计时器。 它本质上是你想要做的,如果你不增加你的价值是什么:重置并重新启动。



Answer 5:

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

我使用的核心基础功能,只是为了避免创建一个NSDate 。 过早的优化? 请把盐递过来。



文章来源: Reset an NSTimer's firing time to be from now instead of the last fire