本文介绍了在 iPhone 上拖动 UIScrollView 时,OpenGL ES 视图中的动画会冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动画透明 OpenGL ES 子视图(Apple 模板 EAGLView 类的修改),它绘制一个旋转球体.就像 Apple 的示例一样,CADisplayLink 在可用的设备上使用.

I have an animated transparent OpenGL ES subview (a modification of Apple's template EAGLView class) which draws a rotating sphere. Just like Apple's example, CADisplayLink is used on devices where available.

在同一个屏幕上,有一个 UIScrollView 包含可以选择的 UIButtons.当用户滚动 UIScrollView 时,我的 EAGLView 的动画会冻结.此行为在 iOS Simulator 4.2 和 iPhone 2G 设备上的 iPhone OS 3.1.3 上重现.

On the same screen, there is a UIScrollView containing UIButtons that can be selected. When the user scrolls the UIScrollView, the animation of my EAGLView freezes. This behavior is reproduced on iOS Simulator 4.2 and on iPhone OS 3.1.3 on an iPhone 2G device.

除了编写我自己的滚动视图之外,关于如何防止 EAGLView 暂停的任何想法?

Any ideas on what to do to prevent pause of the EAGLView, apart from coding my own scroll view?

推荐答案

在滚动期间是否触发 CADisplayLink 取决于您将其添加到运行循环的模式.可能你在某个地方有这个:

Whether CADisplayLink fires during scrolls depends on the mode with which you add it to the run loop. Probably you have this, somewhere:

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

UIApplication 添加了一个运行循环模式,UITrackingRunLoopMode,用于控件中的跟踪",包括滚动视图何时滚动.因此,此时 runloop 将退出默认模式,因此您的显示链接(以及在默认模式下添加的任何计时器、NSURLConnections 等)将无法触发,直到恢复默认模式.

UIApplication adds a run loop mode, UITrackingRunLoopMode, for 'tracking in controls', which includes when a scrollview is scrolling. So at that point the runloop is switched out of the default mode and hence your display link (and also any timers, NSURLConnections, etc, added in the default mode) will fail to fire until default mode is restored.

快速修复:将代码更改为:

Quick fix: change your code to:

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

UITrackingRunLoopMode 被认为是常见的模式之一.

UITrackingRunLoopMode is considered one of the common modes.

花太多时间打断 UIKit 会导致一些非常糟糕的控制响应,所以你需要小心.这将大大偏离主题,但尽管 OpenGL 是模态的,因此对线程不是特别友好,但您可以使用 EAGLSharegroup 在单独的线程上进行渲染,然后将其推送到主线程.

Spending too much time interrupting UIKit can lead to some very poor control responsiveness, so you need to be careful. It'd be to diverge from the topic massively, but although OpenGL is modal and therefore not particularly threading friendly, you can use an EAGLSharegroup to do rendering on a separate thread and then push it onto the main thread.

(2016) Swift3 中的一个示例...

An example in (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
  }

这篇关于在 iPhone 上拖动 UIScrollView 时,OpenGL ES 视图中的动画会冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 10:32