【发布时间】:2012-09-27 18:09:50
【问题描述】:
Brad Larson 针对滚动视图滚动时的CADisplayLink 冻结问题提供了solution。
CADisplayLink 调用了我的 OpenGL ES 绘制方法,我尝试了 Brad 的技术,但无法使其工作。核心问题是我的 OpenGL ES 视图由UIScrollView 托管,当 UIScrollView 滚动时,CADisplayLink 停止触发。
Brad 描述的技术应该让CADisplayLink 即使在滚动期间也能继续触发(通过将其添加到NSRunLoopCommonModes 而不是默认的运行循环模式),并且使用一种花哨的信号量技巧渲染回调应该确保当 UIKit 被占用太多时它不会渲染。
问题在于信号量技巧无论如何都会阻止渲染回调绘制。
首先,我在我的 OpenGL ES 视图的initWithFrame 方法中创建串行 GCD 队列和信号量,如下所示(在主线程上):
frameRenderingQueue = dispatch_queue_create("com.mycompany.crw", DISPATCH_QUEUE_SERIAL);
frameRenderingSemaphore = dispatch_semaphore_create(1);
显示链接已创建并添加到NSRunLoopCommonModes:
CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(renderFrame)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
渲染回调执行 Brad 的技术:
- (void)renderFrame {
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
NSLog(@"return"); // Gets called ALWAYS!
return;
}
dispatch_async(drawingQueue, ^{
@autoreleasepool {
// OpenGL ES drawing code
dispatch_semaphore_signal(frameRenderingSemaphore);
}
});
}
dispatch_semaphore_wait 函数总是返回 YES,因此渲染回调永远不会渲染。即使我不滚动。
我想我在这里错过了一些重要的事情。谁能指出来?
编辑:它似乎只在我调用 dispatch_sync 而不是 dispatch_async 时才有效,但根据 Brad 的说法,dispatch_async 会在这里提供更好的性能。
【问题讨论】:
标签: opengl-es uikit grand-central-dispatch cadisplaylink