在iPhone上绘制几条线和圆时,CGContextStrokePath的性能表现较差

4

我需要在视图上绘制几百条线和圆,并通过计时器函数使它们不断移动,其中我调用[myView setNeedsDisplay]来更新视图。

我从UIView子类(myView)中实现drawRect函数来执行以下操作...

-(void) drawRect:(CGRect)rect {
   CGContextRef context = UIGraphicsGetCurrentContext();

   CGFloat red[4] = { 1, 0, 0, 1};

   CGContextSetLineWidth(context, 1);
   CGContextSetShouldAntialias(context, NO);
   CGContextSetLineCap(context, kCGLineCapSquare);
   CGContextSetStrokeColor(context, red);

   // rects is an array of CGRect of size ~200
   for (int i = 0; i < N; i++) {
      CGContextAddEllipseInRect(context, rects[i]);
   }
   // points is an array of CGPoint of size ~100
   CGContextAddLines(context, points, N);

   CGContextStrokePath(context, color);
}

但是这个速度非常慢。我是否遗漏了什么? 完成一次绘制需要近1秒钟。

1个回答

7
不断重绘物体以实现动画效果是不好的方法。由于显示系统的工作方式,Quartz 绘制是 UI 方面最慢的操作之一。
相反,您需要为每个将被动画化的元素创建单独的图层或视图。这些图层或视图只会绘制一次,然后进行缓存。当这些图层移动时,它们不会被重新绘制,只是合成。这样做可以让即使是 iOS 设备中速度最慢的设备(如第一代 iPhone、iPhone 3G 和第一代 iPod touch)以每秒 60 帧的速度展示多达 100 个图层。
可以将其类比为动画制作。与让动画师手动重新绘制每个帧的所有部分不同,他们使用细胞来在保持不变或仅移动而无需改变形式的框架之间重用元素。这显著减少了制作卡通的工作量。

感谢Brad的快速回复。然而,我的问题在于每次迭代中,我的算法可以返回随机几何形状,因此预先绘制它们然后移动它们有点困难。我相信即使这样做也会有方法。但是现在我已经找到了一个解决方法,将所有东西都绘制在原始内存缓冲区中,然后将其转换为UIImage,并显示它。这似乎更快。 - Abix
@Abix:我不认为那是一个权宜之计,而是实际的解决方案。Brad 不仅仅是在建议一种解决问题的方法,而是在解释 Quartz 单独使用并不适合你的工作。 - Slipp D. Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接