Objective c 重置NSTimer';现在是开火时间,而不是最后一次开火

Objective c 重置NSTimer';现在是开火时间,而不是最后一次开火,objective-c,cocoa-touch,nstimer,Objective C,Cocoa Touch,Nstimer,我有一个NSTimer,它以3秒的间隔触发以减小值。当我执行增加该值的操作时,我希望重新启动计时器,从该点开始计数3秒 例如,如果我增加该值,计时器将在1秒内启动,我想更改该值,使计时器在3秒内启动。我可以使计时器失效并重新创建它吗?或者我可以使用setFireDate:,使用当前日期并添加3秒的间隔来执行此操作吗?是的,您可以使其无效。然后再创建一次 您还可以使用: - (void) myTimedTask { // other stuff this task needs to do

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


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

是的,您可以使其无效。然后再创建一次

您还可以使用:

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

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


在我看来,将-performSelector代码与计时器代码混合使用会导致目标方法的多次执行,因此我不想这样做。

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

文件提到更改启动日期相对昂贵,建议最好销毁并重新创建计时器,除非你经常这么做。然而,为了便于讨论,我不久前突然提出了这一类别。我更喜欢这个,因为它封装了日期调整行为;计时器本身处理它,而不是它的所有者/控制器。不过,我没有这方面的任何性能数据

@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 < /代码>。过早优化?请通过测试。

我做了一些测试,结果表明,重置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];
        }
    }
}
-(无效)测试验证计时器{
对于(int n=0;n<10000;n++){
[testTimer invalidate];
testTimer=nil;
NSTimer*定时器=[NSTimer scheduledTimerWithTimeInterval:3.0
目标:自我
选择器:@selector(不带任何内容:)
用户信息:无
重复:否];
testTimer=计时器;
}
}
-(无效)测试重置计时器{
对于(int n=0;n<10000;n++){
如果([testTimer isValid]){
testTimer.fireDate=[nsdatedatewithtimeintervalsincenow:3.0];
}
}
}

在iPad Air上运行该程序,失效计时器的时间为0.198173秒,重置计时器的时间为0.044207秒。如果性能是您的目标,我建议重置fireDate。这也大大减少了编码工作量。

@zoul,这取决于您想要的混乱程度:-)最后,我使用setFireWithDate,当我增加值时,我还会向计时器发送一条消息,当前日期加上三秒。很有效^^非常感谢。