提高drawRect的性能:

时间:2013-03-09 16:05:29

标签: iphone objective-c xcode

我每隔0.1秒使用NSTimer从网格中绘制单元格。 大小约为96x64 => 6144个细胞/图像。 如果我正在绘制图像而不是(例如)绿色矩形,它会慢4倍!

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    CGContextSetRGBFillColor(context, 0, 0, 0, 1);
    CGContextFillRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
    int cellSize = self.bounds.size.width / WIDTH;
    double xOffset = 0;
    for (int i = 0; i < WIDTH;i++)
    {
        for (int j = 0; j < HEIGHT;j++)
        {                
                NSNumber *currentCell = [self.state.board objectAtIndex:(i*HEIGHT)+j];
                if (currentCell.intValue == 1)
                {
                   [image1 drawAtPoint:CGPointMake(xOffset + (cellSize * i),cellSize * j )];
                }
                else if (currentCell.intValue == 0){
                   [image2 drawAtPoint:CGPointMake(xOffset + (cellSize * i),cellSize * j )];
                }
        }
    }
    UIGraphicsPopContext();
}

如果我想在每个矩形中绘制png或jpg,任何想法如何更快? 图像已经缩放到适当的大小。

4 个答案:

答案 0 :(得分:3)

  • a)不要重绘视图边界之外的图像/视频。

  • b)不要重绘dirtyRect之外的图像/作品

  • c)不要重绘自此以来没有变化的图像/作品 之前的更新。

  • d)使用图层预呈现图像,因此您无需渲染 他们在抽奖时间。

答案 1 :(得分:2)

这种情况正是仪器所针对的。用它。这里提出建议的任何人都在猜测瓶颈是什么。

那就是说,我要猜测瓶颈是什么。您正在使用CPU绘制6114个图像(使用时间分析器确认这一点。找到您的drawRect方法,并检查花费的时间最多。如果是drawInRect,那那就是您的问题)

如果是这种情况,我们如何减少其使用量?一个简单的胜利就是只重绘我们需要绘制的图像。 CALayers让这很容易。删除drawRect方法,为每个图像的视图层添加子图层,并将图像设置为图层的内容属性。无需在图像需要更改时使视图无效,只需将相关图层的内容属性切换为新图像。

关于CALayers的另一个好处是它们可以在GPU上缓存图层内容,这意味着发生的重绘会占用更少的CPU时间,并且当它们发生时不会阻止其余的应用程序。

如果那么多层的开销是不可接受的(再次,Instruments是你的朋友),请查看CAReplicatorLayer。它不如拥有许多CALayers灵活,但允许以最小的开销多次复制单个图像。

答案 2 :(得分:1)

我尝试从性能角度改进您的代码。但是,请检查我对瓶颈的评论。

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    //UIGraphicsPushContext(context); //not needed UIView does it anyway

    //use [UIView backgroundColor] instead of this
    //CGContextSetRGBFillColor(context, 0, 0, 0, 1);
    //CGContextFillRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));

    int cellSize = self.bounds.size.width / WIDTH;
    double xOffset = 0;

    CGRect cellFrame = CGRectMake(0, 0, cellSize, cellSize);
    NSUinteger cellIndex = 0;

    for (int i = 0; i < WIDTH; i++) {
        cellFrame.origin.x = xOffset;

        for (int j = 0; j < HEIGHT; j++, cellIndex++) {                
            cellFrame.origin.y = 0;

            if (CGRectIntersectsRect(rect, cellFrame) {
                NSNumber *currentCell = [self.state.board objectAtIndex:cellIndex];

                if (currentCell.intValue == 1) {
                    [image1 drawInRect:cellFrame];
                }
                else if (currentCell.intValue == 0) {
                    [image2 drawInRect:cellFrame];
                }
            }

            cellFrame.origin.y += cellSize;
        }

        cellFrame.origin.x += cellSize;
    }

    //UIGraphicsPopContext(context); //not needed UIView does it anyway
}

答案 3 :(得分:0)

使用CGRectIntersects检查图像的矩形是否在dirtyRect内,以检查是否需要绘制它。