Анимация в OpenGL ES view зависает, когда UIScrollView перетаскивается на iPhone

У меня есть анимированный прозрачный OpenGL ES subview (модификация класса Apple EAGLView класса), который рисует вращающуюся сферу. Как и пример Apple, CADisplayLink используется на доступных устройствах.

На этом же экране есть UIScrollView, содержащий UIButtons, который можно выбрать. Когда пользователь прокручивает UIScrollView, анимация моего EAGLView зависает. Это поведение воспроизводится на iOS Simulator 4.2 и на iPhone OS 3.1.3 на устройстве iPhone 2G.

Любые идеи о том, что делать, чтобы предотвратить паузу EAGLView, помимо кодирования моего собственного вида прокрутки?

Ответ 1

Возможен ли CADisplayLink во время свитков, зависит от режима, с которым вы добавляете его в цикл выполнения. Возможно, у вас есть это где-то:

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

UIApplication добавляет режим цикла запуска UITrackingRunLoopMode для "отслеживания в элементах управления", который включает в себя прокрутку прокрутки. Таким образом, в этот момент runloop отключается от режима по умолчанию, и поэтому ваша ссылка на изображение (а также любые таймеры, NSURLConnections и т.д., Добавленные в режиме по умолчанию) не сработают, пока не будет восстановлен режим по умолчанию.

Быстрое исправление: измените свой код на:

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

UITrackingRunLoopMode считается одним из общих режимов.

Расходование слишком большого количества времени прерывания UIKit может привести к очень плохой управляемости, поэтому вам нужно быть осторожным. Было бы отвлечься от темы в массовом порядке, но хотя OpenGL является модальным и, следовательно, не особенно дружественным к потоковому использованию, вы можете использовать EAGLSharegroup для рендеринга в отдельном потоке, а затем нажимать его на основной поток.


Пример в (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
  }