2010-11-20 18 views
5

Śledzenie zdarzeń w widoku UIScrollview blokuje główny wątek. Używam głównego wątku do uruchomienia timera, który napędza niektóre animacje - rezultatem tego jest to, że każda interakcja użytkownika z przewijanym widokiem (przeciąganie go w górę lub w dół, itp.) Powoduje zatrzymanie animacji (działającej na głównym biegu). Czy istnieje sposób obejścia tego?Śledzenie zdarzeń w UIScrollView blokuje główny wątek. Jakieś poprawki?

Próbowałem RTFM o NSRunloop (CFRunLoopAddCommonMode et al), ale jest dość zwięzły, co prowadzi mnie do przekonania, że ​​pomijanie priorytetów zdarzeń/priorytetów wątku jest lepiej unikać. Ktoś ma jakiś wgląd?

+1

W wątku głównym można robić tylko rzeczy związane z interfejsem użytkownika, więc nie ma zastosowania do priorytetów wątków. Ciekawi mnie - czy wiesz, czy NSTimers przestają strzelać, czy uruchamia się timery, ale odmawiają zastosowania zmian wprowadzonych w animacji? Czy animacja została wykonana * na * UIScrollView, lub * w * przewijanym widoku? Czy próbujesz animować i zmieniać to samo, co przewijanie przewijania? (Przewiń widok, itd.)? – Brad

+0

Dzięki, Brad - to, co miałem nadzieję (prawdopodobnie niebezpiecznie) zrobić, to dodać tryb EventTracking do głównego runloopa, co pozwoli mu kontynuować działanie równolegle z runloopem EventTracking. Animowana blokada jest wykonywana w zupełnie innym widoku niż ten zawierający przewijany widok. Aby odpowiedzieć na twoje inne pytanie, NSTimer przestaje strzelać całkowicie. Wydaje się być całkowicie zablokowany przez biznes o wyższym priorytecie śledzenia zdarzeń użytkownika w (niespokrewnionym) UIScrollView. –

Odpowiedz

16

Zamiast jednego statycznych konstruktorów NSTimer, należy utworzyć obiekt timera i zaplanować go ręcznie tak:

NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:delayInSeconds] interval:0 target:yourObject selector:yourSelector userInfo:nil repeats:NO]; 
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
[timer release]; 

swoje paramters do initWithFireDate: będzie zupełnie inny, oczywiście, zwłaszcza, że ​​to brzmi jak ty” ponowne użycie powtarzającego się licznika czasu. Myślę, że możesz zobaczyć podstawowy pomysł.

Podczas przewijania pętla uruchamiania przechodzi w tryb, który uniemożliwia wykonywanie zadań "trybu domyślnego". Statyczny NSTimer działa zgodnie z harmonogramem w trybie domyślnym, dlatego nie uruchamia się podczas przewijania. Ręczne planowanie zegara pozwala określić tryb, a NSRunLoopCommonModes zawiera tryb uruchamiania, który jest używany podczas przewijania.

+0

Genialny! Używałem: \t [[NSRunLoop mainRunLoop] addTimer: loopTimer forMode: [NSRunLoop currentMode]]; który wciąż był zablokowany. Twoja poprawka działa idealnie. –

+0

Dzięki za trylion! Ta poprawka drastycznie zwiększa użyteczność mojego leniwego stołu ładującego. – Nailer

0

Jednym z pomysłów jest uruchomienie timera w oddzielnym wątku. Po uruchomieniu timera, musisz mieć to, co trzeba, aby uruchomić na głównym wątku.

Edit:

Ach tak, że całkowicie zapomniał o tym, jak UIScrollView blokuje prawie wszystko. Innym pomysłem (choć bardzo brzydkim) jest sprawdzenie, czy licznik czasu wystrzelił podczas metod delegowania (tj. -scrollviewDidScroll, itp.) Z UIScrollView. To naprawdę hack, ale jest to w zasadzie jedyny sposób, w jaki zdaję sobie sprawę z możliwości wykonania dowolnego kodu podczas przewijania.

+0

Dzięki, tak, faktycznie uruchamiam już zegar animacji w głównym wątku. Wydaje się, że śledzenie zdarzeń użytkowników zza kulis odbywa się z wyższym priorytetem niż wątek główny, więc gdy dzieje się coś ciągłego (jak przewijanie), blokuje główny wątek przez długi czas ... –

+0

@Andy Milburn: Zobacz edytowanie innego pomysłu. –

Powiązane problemy