2009-10-17 9 views
7

Mam NSTimer, który strzela z przerwą 3 sekund na zmniejszenie wartości. Kiedy wykonuję akcję zwiększającą tę wartość, chcę ponownie uruchomić zegar, aby odliczyć 3 sekundy od tego punktu.Zresetuj czas ostrzału NSTimer'a, aby był od teraz zamiast ostatniego pożaru

Na przykład, jeśli zwiększę wartość, a timer uruchomi się w ciągu 1 sekundy, chcę to zmienić i ustawić timer na 3 sekundy zamiast tego. Czy mogę unieważnić licznik i utworzyć go ponownie? Czy mogę to zrobić z setFireDate:, używając bieżącej daty i dodając interwał 3 sekund?

+0

Wreszcie używam setFireWithDate, kiedy zwiększam wartość wysyłam również wiadomość do timera z aktualną datą plus trzy sekundy. Działa^^ Dziękuję Wam bardzo. – emenegro

Odpowiedz

7

Tak, można go unieważnić. I stwórz go ponownie.

Można również użyć:

- (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]; 

} 

zadzwonić myTimedTask aby rozpocząć cykliczne zadanie. Po uruchomieniu możesz zmienić opóźnienie za pomocą zmiennej Opóźnienie lub zatrzymać ją za pomocą weStillWantTimer.

+0

+1, ale z pewnością nie jest * globalny *, prawda? :) – zoul

+0

@zoul, zależy od tego, jak niechlujnie chcesz być :-) – mahboudz

1

Unieważnij timer i odtwórz go. Upewnij się jednak, że nie unieważniasz i zwolnienia timera, chyba że masz pewność, że musisz, ponieważ pętla uruchamiania zachowuje zegary, dopóki nie zostaną unieważnione, a następnie zwalnia je.

Moim zdaniem miksowanie kodu servera z kodem timera prowadzi do wielokrotnego wykonywania metod docelowych, więc trzymałem się z dala od tego.

1

Tak, unieważnienie i ponowne utworzenie stopera będzie działało. Zasadniczo to, co chcesz zrobić, jeśli nie zwiększasz swojej wartości: zresetuj i zacznij od początku.

1

W setFireDate: Docs wspomnieć, że zmiana daty ogień jest stosunkowo drogie, co sugeruje, że może być lepiej, aby zniszczyć i odtworzyć timer, chyba że robisz tak dużo. Jednak ze względu na argumenty poruszyłem tę kategorię jakiś czas temu. Wolę to, ponieważ hermetyzuje zachowanie dostosowania daty; sam timer obsługuje go, a nie jego właściciela/kontrolera. Nie mam jednak żadnych danych na temat wydajności.

@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 

Użyłem funkcji Core Foundation tylko po to, aby uniknąć tworzenia NSDate. Przedwczesna optymalizacja? Proszę podać sól.

3

Zrobiłem małe testy i okazało się, że resetowanie fireDate jest około cztery razy szybsze niż unieważnianie i ponowne tworzenie timera. Po pierwsze, stworzyć czasomierz, który wywołuje metodę DoNothing:

if (!testTimer) { 
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                 target:self 
                selector:@selector(doNothing:) 
                userInfo:nil 
                repeats:NO]; 
    testTimer = timer; 
} 

Oto kod testu:

- (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]; 
     } 
    } 
} 

Running że na iPad Air daje 0.198173 s dla invalidatingTimer i 0.044207 s dla resettingTimer. Jeśli wydajność jest Twoim celem, polecam zresetować fireDate. Jest to również nieco mniejszy wysiłek związany z kodowaniem.

Powiązane problemy