It's possible that slow updates on the main thread triggered by the CADisplayLink are what's breaking UIScrollView's scrolling behavior here. Your OpenGL ES rendering might be taking long enough for each frame to throw off the timing of a UIScrollView when using NSRunLoopCommonModes
for the CADisplayLink.
One way around this is to perform your OpenGL ES rendering actions on a background thread by using a Grand Central Dispatch serial queue. I did this in my recent update to Molecules (source code for which can be found at that link), and in testing with using NSRunLoopCommonModes
on my CADisplayLink, I don't see any interruption of the native scrolling behavior of a table view that's onscreen at the same time as the rendering.
For this, you can create a GCD serial dispatch queue and use it for all of your rendering updates to a particular OpenGL ES context to avoid two actions writing to the context at the same time. Then, within your CADisplayLink callback you can use code like the following:
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
return;
}
dispatch_async(openGLESContextQueue, ^{
[EAGLContext setCurrentContext:context];
// Render here
dispatch_semaphore_signal(frameRenderingSemaphore);
});
where frameRenderingSemaphore
is created earlier as follows:
frameRenderingSemaphore = dispatch_semaphore_create(1);
This code will only add a new frame rendering action onto the queue if one isn't in the middle of executing. That way, the CADisplayLink can fire continuously, but it won't overload the queue with pending rendering actions if a frame takes longer than 1/60th of a second to process.
Again, I tried this on my iPad here and found no disruption to the scrolling action of a table view, just a little slowdown as the OpenGL ES rendering consumed GPU cycles.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…