为啥即使我不滚动,dispatch_semaphore_wait() 也一直返回 YES?
Posted
技术标签:
【中文标题】为啥即使我不滚动,dispatch_semaphore_wait() 也一直返回 YES?【英文标题】:Why does dispatch_semaphore_wait() return YES all the time even when I'm not scrolling?为什么即使我不滚动,dispatch_semaphore_wait() 也一直返回 YES? 【发布时间】: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
会在这里提供更好的性能。
【问题讨论】:
【参考方案1】:我不得不把代码的结构改成这样:
- (void)renderFrame
dispatch_async(drawingQueue, ^
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
return;
@autoreleasepool
// Drawing code...
dispatch_semaphore_signal(frameRenderingSemaphore);
);
在我以这种方式对其进行重组后,dispatch_semaphore_wait
调用一直停止返回 YES。我不确定这是否实际上只是禁用了 Brad 的信号量等待技巧。但它有效。
【讨论】:
以上是关于为啥即使我不滚动,dispatch_semaphore_wait() 也一直返回 YES?的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使在自定义 OnTouchListener 实现后 RecyclerView 仍然滚动?
为啥即使我覆盖 touchesMoved:withEvent:,UIScrollView 的子类仍会滚动?
即使没有人告诉它,为啥 QScrollArea 在多点触控上滚动?