Brad Larson为滚动视图滚动时的冻结问题提供了解决方案。CADisplayLink
我的 OpenGL ES 绘制方法由 a 调用CADisplayLink
,我尝试了 Brad 的技术,但无法使其工作。核心问题是我的 OpenGL ES 视图由 a 托管UIScrollView
,当 UIScrollView
滚动时,CADisplayLink
停止触发。
Brad 描述的技术应该让CADisplayLink
即使在滚动期间也能继续触发(通过将其添加到NSRunLoopCommonModes
而不是默认的 runloop 模式),并且使用花哨的信号量技巧渲染回调应该确保它在 UIKit 时不会渲染太占了。
问题在于信号量技巧无论如何都会阻止渲染回调绘制。
首先,我在我的 OpenGL ES 视图的方法中创建串行 GCD 队列和信号量,initWithFrame
如下所示(在主线程上):
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
,但根据布拉德的说法,它dispatch_async
会在这里提供更好的性能。