并发drawRect:

时间:2013-03-30 15:01:33

标签: objective-c cocoa grand-central-dispatch nsview

我有大量的对象(通常是500 - 2000)渲染到屏幕上。不幸的是,渲染目前并不是很精彩。

每个对象都需要执行一些占用大部分时间的计算,最后将自己绘制到屏幕上,即目前我的drawRect:方法看起来基本上是这样的:
我省略了一些简单的优化,例如为了便于阅读而检查绑定rects与dirtyRect

- (void)drawRect:(NSRect)dirtyRect
{
   for (Thing *thing in [self getThings])
   {
        [thing prepareForDrawing];
        [thing draw];
   }
}

明显的并发处理候选者,对吧?

我无法想出一个很好的方法来将准备与实际绘图操作分离,即并行执行预处理并以某种方式对绘图命令进行排队,直到完成所有处理,然后一次性全部渲染。

然而,考虑到GCD的善良,我想出了以下方案 这对我来说听起来不错,但是对于GCD来说是新手,在公开发布四周之后遇到奇怪的多线程问题或者只是使用一个糟糕的GCD设计模式我觉得我会要求反馈。

任何人都可以看到这种方法存在问题 - 潜在问题或更好的解决方案吗?

- (void)drawRect:(NSRect)dirtyRect
{
   [[self getThings] enumerateObjectsWithOptions:NSEnumerationConcurrent
                                      usingBlock:^(id obj, NSUInteger idx, BOOL *stop)
   {
      // prepare concurrently
      Thing *thing = (Thing*)obj;
      [thing prepareForDrawing];

      // always draw in main thread
      dispatch_async(dispatch_get_main_queue(), ^{
         [thing draw];
      });
   }
}

1 个答案:

答案 0 :(得分:3)

这不起作用,因为[thing draw]的调用将在-drawRect:完成后发生。图形上下文将不再有效用于绘制到该视图中。

为什么“事情”没有事先准备好? -drawRect:用于绘图,而不是计算。任何必要的昂贵计算都应该提前完成。