我需要帮助来更好地了解其方式CADisplayLink
和drawRect
行为,以便我可以弄清楚如何将我的应用程序的帧速率保持在平稳的 60fps。到目前为止,我的(可能是不正确的)理解如下:
1)CADisplayLink
在显示刷新时调用指定的选择器(所谓的“垂直同步”事件;大约每 16 毫秒)。
2) iOS 使用双缓冲,这意味着在显示一个帧缓冲区时,我们可以准备(绘制)另一个,并且在下一个垂直同步事件时交换两者。
3)因此,从显示链接触发的那一刻起,我有大约 16ms 的时间来确保下一帧所需的所有计算和绘图都已完成,以便在交换缓冲区和屏幕刷新时一切就绪。
4) 自定义 UIView 的 drawRect 方法绘制到后台缓冲区,所以在drawRect
调用该方法后的下一个 v-sync 事件中显示任何自定义绘制。
这真的是这样吗?(如果下一个垂直同步事件发生在我完成绘制到后台缓冲区之前会发生什么?)
那么,我应该如何使用CADisplayLink
重绘自定义 UIViews 呢?我尝试setNeedsDisplay
在显示链接触发时调用,但是在 drawRect 方法实际开始之前有一个延迟:
2014-12-10 19:17:21.000 myApp[39487:60b] Display link fired.
2014-12-10 19:17:21.001 myApp[39487:60b] Sending setNeedsDisplay
2014-12-10 19:17:21.012 myApp[39487:60b] drawRect beginning
2014-12-10 19:17:21.013 myApp[39487:60b] drawRect finished
2014-12-10 19:17:21.017 myApp[39487:60b] Display link fired.
2014-12-10 19:17:21.018 myApp[39487:60b] Sending setNeedsDisplay
2014-12-10 19:17:21.029 myApp[39487:60b] drawRect beginning
2014-12-10 19:17:21.031 myApp[39487:60b] drawRect finished
2014-12-10 19:17:21.033 myApp[39487:60b] Display link fired.
这是一个非常简化的示例,该方法中几乎没有绘制drawRect
。我的一些更复杂的 drawRect 可能需要 10 毫秒才能完成。drawRect
但是从启动到下一次显示刷新之间只有 5ms !另外,在显示链接触发和 drawRect 开始之间显然“浪费”了 11 毫秒!我该如何利用这段时间?
如果我尝试直接在显示链接选择器中调用drawRect
,我会得到如下信息:
2014-12-10 19:24:41.000 myApp[39495:60b] Display link fired.
2014-12-10 19:24:41.001 myApp[39495:60b] Sending setNeedsDisplay
2014-12-10 19:24:41.002 myApp[39495:60b] drawRect beginning
2014-12-10 19:24:41.003 myApp[39495:60b] drawRect finished
2014-12-10 19:24:41.016 myApp[39495:60b] Display link fired.
2014-12-10 19:24:41.017 myApp[39495:60b] Sending setNeedsDisplay
2014-12-10 19:24:41.018 myApp[39495:60b] drawRect beginning
2014-12-10 19:24:41.020 myApp[39495:60b] drawRect finished
2014-12-10 19:24:41.032 myApp[39495:60b] Display link fired.
现在我的绘图代码似乎有足够的时间来执行。但是,Apple 文档明确指出“您永远不应该drawRect
自己直接调用该方法”。那么为什么这是错误的做法呢?以及如何最大限度地利用我必须绘制每一帧的 16 毫秒?