使用/不使用dispatch_async

时间:2015-06-02 09:01:24

标签: ios glkview

我正在使用按需渲染构建自定义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会有所作为呢?

所以现在我有三个问题:

  1. “Jo”日志之间的那一秒发生了什么?
  2. 为什么dispatch_async有所作为?
  3. 在生产中使用这种方法是不好的做法吗?
  4. 非常感谢!

    修改

    还有一件事我不明白。

    当我使用[self setNeedsDisplay];方法时,主队列上的所有其他调用似乎都在挨饿。触摸事件不再触发,RestKit的回调永远不会被传递。 [self setNeedsDisplay];以某种方式不会在队列末尾添加,而是在开头添加吗?

1 个答案:

答案 0 :(得分:0)

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

因此,当您从其他线程调用它时,实际上标记了需要重绘的视图,但是您没有通知运行循环实际触发重绘过程。

所以:

  1. 没什么特别的。它只是在等待。
  2. 它会触发刷新管道,从而产生差异。
  3. 根本不是一个不好的做法,但是如果以后有更多的元素要调用它,请小心你如何做这个程序。
  4. 好/坏的做法取决于具体情况,但我要做的是创建一个包含显示链接的类。我会添加两个方法,例如retainAnimationreleaseAnimation。这两个将增加或减少整数值retainAnimationCount然后覆盖其setter,以便:

    1. 如果计数从零开始增加,则显示链接开始
    2. 如果计数减少到零,则显示链接停止
    3. 然后,显示链接将调用委托,给定块或仅为给定视图调用setNeedsDisplay的硬编码。类本身可以将输出调用恢复为主线程,但可以从任何线程调用释放和保留调用。

      修改

      如果在您的情况下使用此类,您将在动画开始后调用retain方法,并在完成动画后调用release方法。所有其余的应该已经在课堂上处理了。如果您有多个"动画"对象不会有刷新方法的额外调用,没有交错问题,何时开始或何时停止,你从哪个线程调用它...但确保你没有将retain count属性标记为{{ 1}}因为你仍然应该保持线程安全。