2015-06-02 42 views
0

我正在使用按需渲染构建自定义GLKView。大多数情况下,视图只会重新绘制触摸事件(并且这是行得通的),但有时会有短的动画,我想在循环中重绘。从GLKView drawRect调用setNeedsDisplay with/without dispatch_async

我第一次尝试是这样的:

-(void)drawRect:(CGRect)rect { 
    NSLog(@"Jo"); 

    glClearColor(1, 0, 0, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    [self setNeedsDisplay]; 
} 

我的理解,从Android未来是,这应保持尽可能快地清除屏幕和记录大量的“乔”的。 实际情况是什么“乔”记录每秒大约一次,观点根本就不会被清除,但CPU使用保持为0

如果我改变

[self setNeedsDisplay]; 

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self setNeedsDisplay]; 
}); 

一切正如预期一样。

据我所知,drawRect无论如何都是从主线程调用的,那么为什么dispatch_async会有所作为?

所以现在我有三个问题:

  1. 什么在那一秒的“乔”日志之间是怎么回事?
  2. 为什么dispatch_async有所作为?
  3. 在生产中使用这种方法不好吗?

非常感谢!

编辑:

有一件事我不明白。

当我使用[self setNeedsDisplay];方法时,主队列上的所有其他调用似乎都很匮乏。触摸事件不再触发,并且RestKit的回调不会传递。不知何故[self setNeedsDisplay];不会在队列末尾添加,但在开始?

回答

0

在那一秒内没有任何事情发生,因为没有任何东西触发重绘。这个流水线非常复杂,但在主线程上调用时,如setNeedsDisplay等方法会做更多工作,因为它会通知窗口层次结构它已更改,并将重绘需要重绘的元素。这条管道很可能连接到只能从主线程访问的主运行循环。

所以当你从其他线程调用它时,你实际上标记了它需要重绘的视图,但是你不通知运行循环来实际触发重绘过程。

所以:

  1. 没有什么特别的实在。它只是在等待。
  2. 它触发刷新管道时会产生差异。
  3. 不是一个坏习惯,但要小心如何做这个过程,如果以后更多的元素将这样调用。

对于好的/坏的做法取决于情况,但我会做的是创建一个包含显示链接的类。我会添加2个方法,如retainAnimationreleaseAnimation。这些2会增加或减少一个整数值retainAnimationCount然后覆盖其设定器,使得:

  1. 如果计数是从零增大的显示链接开始
  2. 如果计数减小到零的显示链接停止

然后,显示链接会针对给定视图调用setNeedsDisplay的代理,给定块或简单硬编码调用。类本身可以将输出调用恢复到主线程,但释放和保留调用可以从任何线程调用。

编辑:

如何这个类是在你的情况下使用,你会调用保留方法一旦你的动画开始,一旦完成动画释放方法。所有其他的应该已经在课堂上处理了。好处大多是如果你有多个“动画”对象,就不会有额外的刷新方法调用,没有交错问题,什么时候开始或什么时候停止,你调用它的线程是什么......但确保您不要将保留计数属性标记为nonatomic,因为您应该保持线程安全。

相关问题