我有一個NSTimer
,它以3秒的時間間隔開火以降低數值。當我做一個增加這個值的動作時,我想重新啓動計時器,從那一點開始計算3秒。將NSTimer的開火時間重置爲從現在開始而不是最後一次開火
例如,如果我增加該值並且定時器將在1秒內觸發,我想改變它並使定時器在3秒鐘內觸發。我可以使計時器無效並重新創建嗎?或者我可以用setFireDate:
做到這一點,使用當前日期並添加3秒的時間間隔?
我有一個NSTimer
,它以3秒的時間間隔開火以降低數值。當我做一個增加這個值的動作時,我想重新啓動計時器,從那一點開始計算3秒。將NSTimer的開火時間重置爲從現在開始而不是最後一次開火
例如,如果我增加該值並且定時器將在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開始重複任務。一旦啓動,您可以使用varyDelay更改延遲或使用weStillWantTimer停止它。
使計時器失效並重新創建它。但是,請確保您不會使和無效,除非您確定需要運行循環,因爲運行循環會保留計時器,直到它們失效並自行釋放它們。
在我看來,混合-performSelector代碼與計時器代碼導致多個目標方法的執行,所以我會遠離那個。
是的,無效和重新創建計時器將工作。如果你沒有增加你的價值,它基本上是你想要做的:重新設置並重新開始。
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
。過早優化?請通過鹽。
我做了一些測試,結果發現重置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。這也是相當少的編碼工作。
最後,我使用setFireWithDate,當我增加值時,我也發送消息到當前日期加上三秒鐘的計時器。它工作^^ 非常感謝你。 – emenegro 2009-10-19 10:17:40