2010-02-09 15 views
22

Czy istnieje prostszy sposób oczekiwania na określony czas w Cocoa niż to, co wymyśliłem poniżej?Oczekiwanie na określony czas w kakao

- (void) buttonPressed { 
    [self makeSomeChanges]; 

    // give the user some visual feedback and wait a bit so he can see it 
    [self displayThoseChangesToTheUser]; 
    [self performSelector:@selector(buttonPressedPart2:) withObject:nil afterDelay:0.35]; 
} 

- (void) buttonPressedPart2: (id)unused { 
    [self automaticallyReturnToPreviousView]; 
} 

Żeby było jasne, nie ma funkcjonalny problem z tym kodem - moim jedynym wołowiny jest stylistyczny jeden. W moim przypadku przepływ jest na tyle prosty, że działa, ale staram się go enkapsulować lub wrzucać pewne warunki i rzeczy mogą okazać się brzydkie. To było trochę dokuczliwy na mnie, że nie mogę znaleźć sposób, aby czekać, a następnie powrócić do tego samego punktu w kodzie tak (fikcyjnej) Przykład:

- (void) buttonPressed { 
    [self doStuff]; 
    [UIMagicUnicorn waitForDuration:0.35]; 
    [self doStuffAfterWaiting]; 
} 

Odpowiedz

61

Jest

usleep(1000000); 

i

[NSThread sleepForTimeInterval:1.0f]; 

z których oba będą spać przez 1 sekundę.

+8

i oba zablokuje wątek od robienia czegokolwiek innego. źle, jeśli jest w głównym U.I. wątek. – pestilence669

+3

Prawda. Jeśli potrzebujesz, aby interfejs był responsywny w tym okresie, podejście zasugerowane w pytaniu, NSTimer uruchamiające się raz (jak sugerujesz) lub wątek tła wykonujący to opóźnienie byłoby lepsze. –

+0

Dzięki - właśnie o to się zastanawiałem, prawdopodobnie natknęłbym się na to, gdyby "sen" był jednym z wielu synonimów "oczekiwania", o którym myślałem. Dziękuję również Pestilence za ostrzeżenia o tym, kiedy * nie * używać tych. –

2

Prawdopodobnie chcesz użyć NSTimer i mieć wyślij wiadomość "doStuffAfterWaiting" jako swoje wywołanie zwrotne. Każdy rodzaj "snu" blokuje wątek, dopóki się nie obudzi. Jeśli jest w twoim U.I. wątku, spowoduje to, że Twoja aplikacja stanie się "martwa". Nawet jeśli tak nie jest, jest to zła forma. Metoda wywołania zwrotnego zwolni procesor CPU do wykonywania innych zadań, dopóki nie zostanie osiągnięty określony czas.

Ten przykład ma zastosowania i omawia różnice w tym, w jaki sposób utworzyć swój zegar. &

Oczywiście performSelector: afterDelay: robi to samo.

3

Nie jestem pewien, czy istnieje (jeszcze), ale z blokami w 10.6 (lub PLBlocks w 10.5 i na iPhonie) powinno być całkiem łatwo napisać małe opakowanie, takie jak performBlock:afterDelay:, które robi dokładnie to, co chcesz bez potrzeba snu całej nić. Byłby naprawdę przydatnym małym kawałkiem kodu.

Mike Ash ma written about an approach like this on his blog:

NSString *something = ...; 
RunAfterDelay(0, ^{ 
    NSLog(@"%@", something); 
    [self doWorkWithSomething: something]; 
}); 
2

Co jest nie tak z prostego usleep? Chodzi mi o to, że poza "czystością kakao", jest ona o wiele krótsza niż inne rozwiązania :)

+2

Blokuje wątek. Jeśli zostanie wywołany w głównej części, skutecznie zabijesz pętlę uruchamiania, a aplikacja będzie wyglądać na "martwą". – pestilence669

+3

Następnie nie dzwoń z głównego numeru – Charlie

10

Oto sposób NSTimer tego robienia. Może być jeszcze brzydsza niż metoda, z której korzystasz, ale pozwala powtarzać zdarzenia, więc wolę ją.

[NSTimer scheduledTimerWithTimeInterval:0.5f 
           target:self 
           selector: @selector(doSomething:) 
           userInfo:nil 
           repeats:NO]; 

Chcesz uniknąć czegoś takiego jak usleep(), który po prostu zawiesi twoją aplikację i sprawi, że nie będzie reagować.

+1

Myślę, że masz na myśli 'NSTimer', a nie' NSThread'. –

+7

"' Chcesz uniknąć czegoś takiego jak usleep(), który po prostu zawiesi twoją aplikację i sprawi, że poczujesz się nieuczciwy. "" Na pewno jest to prawdą tylko wtedy, gdy nazwałeś 'usleep' z głównego wątku. – chown

0

Jeśli nie przeszkadza asynchronicznego rozwiązanie, tutaj przejść:

[[NSOperationQueue currentQueue] addOperationWithBlock:^{ 
    [self doStuffAfterWaiting]; 
}];