2009-10-17 38 views
7

我有一個NSTimer,它以3秒的時間間隔開火以降低數值。當我做一個增加這個值的動作時,我想重新啓動計時器,從那一點開始計算3秒。將NSTimer的開火時間重置爲從現在開始而不是最後一次開火

例如,如果我增加該值並且定時器將在1秒內觸發,我想改變它並使定時器在3秒鐘內觸發。我可以使計時器無效並重新創建嗎?或者我可以用setFireDate:做到這一點,使用當前日期並添加3秒的時間間隔?

+0

最後,我使用setFireWithDate,當我增加值時,我也發送消息到當前日期加上三秒鐘的計時器。它工作^^ 非常感謝你。 – emenegro 2009-10-19 10:17:40

回答

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

+0

+1,但肯定不是* global *,對不對? :) – zoul 2009-10-17 19:33:54

+0

@zoul,取決於你想成爲多麼凌亂:-) – mahboudz 2009-10-18 02:10:49

1

使計時器失效並重新創建它。但是,請確保您不會使無效,除非您確定需要運行循環,因爲運行循環會保留計時器,直到它們失效並自行釋放它們。

在我看來,混合-performSelector代碼與計時器代碼導致多個目標方法的執行,所以我會遠離那個。

1

是的,無效和重新創建計時器將工作。如果你沒有增加你的價值,它基本上是你想要做的:重新設置並重新開始。

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 

我已經使用了核心基礎功能只是爲了避免創建一個NSDate。過早優化?請通過鹽。

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上的空氣產生0.198173 S表示invalidatingTimer和0.044207 S代表resettingTimer。如果性能是您的目標,我建議重置fireDate。這也是相當少的編碼工作。