我有NSTimer
以3秒的间隔触发以减少值。当我执行一个增加该值的操作时,我想重新启动计时器,从那时起计算3秒钟。
例如,如果我增加值并且计时器将在1秒内触发,我想改变它并使计时器在3秒内激活。我可以使计时器无效并再次创建吗?或者我可以使用setFireDate:
,使用当前日期并添加3秒的间隔吗?
答案 0 :(得分: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来启动定期任务。一旦启动,您可以使用varyDelay更改延迟或使用weStillWantTimer将其停止。
答案 1 :(得分:3)
我做了一些测试,结果发现重置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秒用于invalidatingTimer和0.044207秒用于resettingTimer。如果性能是您的目标,我建议重置fireDate。它的编码工作量也相当少。
答案 2 :(得分:1)
使计时器无效并重新创建它。但是,请确保不要使和释放计时器失效,除非您确定需要,因为运行循环会保留计时器,直到它们失效,然后自行释放它们。
在我看来,将-performSelector代码与定时器代码混合会导致目标方法的多次执行,所以我会远离它。
答案 3 :(得分:1)
是的,无效并重新创建计时器将起作用。如果你没有增加价值,它本质上就是你想要做的事情:重置并重新开始。
答案 4 :(得分: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
。过早优化?请传盐。