Возможно, что медленное обновление основного потока, запускаемое CADisplayLink, является тем, что нарушает поведение прокрутки UIScrollView здесь. Ваш рендеринг OpenGL ES может занять достаточно много времени для каждого кадра, чтобы отбросить синхронизацию UIScrollView при использовании NSRunLoopCommonModes
для CADisplayLink.
Одним из способов решения этой проблемы является выполнение действий рендеринга OpenGL ES в фоновом потоке с использованием последовательной очереди Grand Central Dispatch. Я сделал это в своем недавнем обновлении до Molecules (исходный код которого можно найти по этой ссылке), и при тестировании с использованием NSRunLoopCommonModes
на моем CADisplayLink я не вижу никакого прерывания нативного поведение прокрутки табличного представления, которое отображается на экране одновременно с рендерингом.
Для этого вы можете создать очередь последовательной отправки GCD и использовать ее для всех ваших обновлений рендеринга в конкретный контекст OpenGL ES, чтобы избежать двух действий, одновременно записывающих контекст. Затем в вашем обратном вызове CADisplayLink вы можете использовать код, подобный следующему:
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
return;
}
dispatch_async(openGLESContextQueue, ^{
[EAGLContext setCurrentContext:context];
// Render here
dispatch_semaphore_signal(frameRenderingSemaphore);
});
, где frameRenderingSemaphore
создан ранее следующим образом:
frameRenderingSemaphore = dispatch_semaphore_create(1);
Этот код будет добавлять новое действие рендеринга кадров в очередь, только если он не находится в середине выполнения. Таким образом, CADisplayLink может запускаться непрерывно, но он не будет перегружать очередь ожидающими действиями рендеринга, если обработка кадра занимает более 1/60 секунды.
Опять же, я попробовал это на своем iPad здесь и не обнаружил нарушения прокрутки в представлении таблицы, только небольшое замедление, поскольку рендеринг OpenGL ES потреблял циклы графического процессора.