2011-02-02 5 views
22

Mam animowane przezroczyste podglądy OpenGL ES (modyfikacja klasy EAGLView szablonu Apple), które rysuje obracającą się kulę. Podobnie jak przykład Apple'a, CADisplayLink jest używany na urządzeniach, gdzie są dostępne.Animacja w widoku OpenGL ES zawiesza się, gdy narzędzie UIScrollView jest przeciągane na iPhonie

Na tym samym ekranie istnieje opcja UIScrollView zawierająca UIButtony, które można wybrać. Gdy użytkownik przewinie widok UIScrollView, animacja mojego EAGLView zawiesza się. To zachowanie jest odtwarzane w systemie iOS Simulator 4.2 oraz w systemie iPhone OS 3.1.3 na urządzeniu iPhone 2G.

Jakieś pomysły, co zrobić, aby zapobiec wstrzymaniu EAGLView, oprócz kodowania mojego własnego widoku przewijania?

+0

2016 - Wydawałoby się, że ** commonModes ** jest rzeczywiście rozwiązanie dla typowych nowoczesnych iOS.. Zobacz: http://stackoverflow.com/a/4878182/294884 To dość niewiarygodne, że przez pięć lat nie było żadnej kontroli jakości. – Fattie

Odpowiedz

51

To, czy CADisplayLink strzela podczas przewijania, zależy od trybu, w którym zostanie dodane do pętli uruchamiania. Prawdopodobnie masz to gdzieś:

[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

UIApplication dodaje tryb pętli biegać, UITrackingRunLoopMode, za „śledzenie w kontroli”, który zawiera kiedy Scrollview jest przewijanie. Więc w tym momencie runloop zostanie wyłączony z trybu domyślnego, a zatem twoje łącze wyświetlania (a także dowolne zegary, NSURLConnections itd., Dodane w trybie domyślnym) nie zostanie uruchomione, dopóki nie zostanie przywrócony tryb domyślny.

Szybka poprawka: zmienić swój kod do:

[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 

UITrackingRunLoopMode jest uważana za jedną z najczęstszych sposobów.

Spędzanie zbyt dużej ilości czasu przerywającego UIKit może prowadzić do bardzo złej odpowiedzi kontrolnej, więc musisz zachować ostrożność. Byłoby odejście od tematu masowo, ale chociaż OpenGL jest modalny i dlatego nie jest szczególnie przyjazny dla wątków, możesz użyć grupy EAGLShare do renderowania w oddzielnym wątku, a następnie wepchnąć go do głównego wątku.


Przykładem w (2016) Swift3 ...

let d = CADisplayLink(target: self, selector: #selector(ThisClassName.updateAlpha)) 
d.add(to: RunLoop.current, forMode: RunLoopMode.commonModes) 


//and then, for example... 
func updateAlpha() { 
    let a = leader.layer.presentation()?.value(forKey: "opacity") as! CGFloat 
    follower.alpha = a 
    } 
+0

Dzięki! W przypadku tego projektu nie martwię się o blokowanie UIKit, ponieważ właśnie renderuję teksturowaną kulę w GUI, więc GL powinien zostawić dużo czasu na przetwarzanie UIKit :-) –

+3

Tylko mały dodatek! Chociaż działa to świetnie, to jednak powoduje błąd na urządzeniach z systemem iOS4, gdzie funkcja UIScrollView nigdy nie przechwytuje zdarzenia "dotknięcia" i zawiesza się w trybie przewijania. To nie pojawia się w Symulatorach iOS4 ani na moim iPhone2G z iOS3.1.3. Rozwiązanie okazało się dość proste: przełączyłem się na stronę kodową opartą na NSTimer, nawet jeśli displaylink jest obsługiwany i zaplanowałem NSTimer w NSRunLoopCommonModes. –

+1

Zobacz to pytanie, aby uzyskać więcej informacji na temat tego rozwiązania: http://stackoverflow.com/questions/5944050/cadisplaylink-opengl-rendering-breaks-uiscrollview-behaviour –