当使用CGContextDrawLinearGradient时,如何优化UITableViewCell渲染

时间:2011-04-26 22:45:38

标签: iphone performance ios uitableview core-graphics

我有一个UITableView,我试图获得最佳的滚动性能。

单元格不包含任何子视图,所有都在drawRect方法中完成。

每个单元格顶部有一条白线,底部有灰线,顶部和底部之间有线性渐变。除此背景外还有一些文字和图片。

从使用乐器我可以看出,滚动时运行时的主要部分(> 50%)来自线性渐变的绘制。实际上几乎所有这些都来自对CGContextDrawLinearGradient的调用。

有没有一种优化方法?我在想,要么以某种方式缓存线性渐变,要么以另一种方式绘制它...也许绘制一个像素宽然后拉伸它?

以下是我的一些代码:

- (void)drawRect:(CGRect)rect  
{  
  [self drawCellBackground:rect];  
  [self drawSeparator:rect];  
  ....
}

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

  CGColorRef notQuiteWhiteColor = [UIColor colorWithRed:245.0/255.0 green:245.0/255.0 
                                             blue:245.0/255.0 alpha:1.0].CGColor;
  CGColorRef lightGrayColor = [UIColor colorWithRed:235.0/255.0 green:235.0/255.0 
                                             blue:235.0/255.0 alpha:1.0].CGColor;

  drawLinearGradient(context, rect, notQuiteWhiteColor, lightGrayColor);
}

从单独的.c文件:

void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef  endColor)
{
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGFloat locations[] = { 0.0, 1.0 };

  NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil];

  CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, 
                                                  (CFArrayRef) colors, locations);

  CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
  CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

  CGContextSaveGState(context);
  CGContextAddRect(context, rect);
  CGContextClip(context);
  CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
  CGContextRestoreGState(context);

  CGGradientRelease(gradient);
  CGColorSpaceRelease(colorSpace);
}

2 个答案:

答案 0 :(得分:4)

如果你绝对想坚持使用drawRect :(我认为它比旧设备上的单独视图提供更好的性能),为什么不将你的渐变渲染成CGImage或UIImage,然后使用它来绘制-drawRect:?< / p>

此外,您可以提前创建渐变:

static CGGradientRef GetCellBackgroundGradient()
{
    static CGGradientRef gradient = NULL ;
    if ( !gradient )
    {
        gradient = // create your CGGradientRef here
    }

    return gradient;
}

对于高性能代码,您希望尽可能多地预分配内存(内存/对象)。

答案 1 :(得分:2)

您是否正确重用表格视图?如果是这样,在这种情况下,我认为您最好在表格视图上使用子视图,而不是在drawRect:中进行所有绘图。通过使用子视图,并假设所有单元格的梯度相同,每个可重用单元格只需绘制一次渐变。当它与新内容一起被回收时,只需要更新文本和图像视图,而不必再次绘制渐变。