我正在使用按需渲染构建自定义GLKView
。大多数情况下,视图只会重新绘制触摸事件(这是有效的),但有时会有短动画,我想在循环中重绘。
我的第一次尝试看起来像这样:
-(void)drawRect:(CGRect)rect {
NSLog(@"Jo");
glClearColor(1, 0, 0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[self setNeedsDisplay];
}
我对Android
的理解是,这应该尽快清除屏幕并记录大量的“Jo”。
实际发生的是“Jo”每秒大约记录一次,视图从未被清除,但CPU
使用仍为0。
如果我改变
[self setNeedsDisplay];
到
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplay];
});
一切都与预期完全一致。
据我所知,drawRect
是从主线程调用的,那么为什么dispatch_async
会有所作为呢?
所以现在我有三个问题:
dispatch_async
有所作为?非常感谢!
修改
还有一件事我不明白。
当我使用[self setNeedsDisplay];
方法时,主队列上的所有其他调用似乎都在挨饿。触摸事件不再触发,RestKit的回调永远不会被传递。 [self setNeedsDisplay];
以某种方式不会在队列末尾添加,而是在开头添加吗?
答案 0 :(得分:0)
在那一秒钟内,没有任何事情发生,因为没有任何事情触发重绘。这个管道非常复杂,但setNeedsDisplay
等方法在主线程上调用时会做更多的工作,因为它会通知窗口层次结构它有更改,并会重绘重绘所需的元素。此管道很可能连接到主运行循环,只能从主线程访问。
因此,当您从其他线程调用它时,实际上标记了需要重绘的视图,但是您没有通知运行循环实际触发重绘过程。
所以:
好/坏的做法取决于具体情况,但我要做的是创建一个包含显示链接的类。我会添加两个方法,例如retainAnimation
和releaseAnimation
。这两个将增加或减少整数值retainAnimationCount
然后覆盖其setter,以便:
然后,显示链接将调用委托,给定块或仅为给定视图调用setNeedsDisplay
的硬编码。类本身可以将输出调用恢复为主线程,但可以从任何线程调用释放和保留调用。
修改强>
如果在您的情况下使用此类,您将在动画开始后调用retain方法,并在完成动画后调用release方法。所有其余的应该已经在课堂上处理了。如果您有多个"动画"对象不会有刷新方法的额外调用,没有交错问题,何时开始或何时停止,你从哪个线程调用它...但确保你没有将retain count属性标记为{{ 1}}因为你仍然应该保持线程安全。