开发者

iPhone - Optimizing drawRect

I have overriden an UIView to make some custom draw :

// ========================================================================================
- (void) drawRect:(CGRect)rect {

    float alphaStep = (kMaxAlpha - kMinAlpha) / (self.nbLines - 1);
    float alphaValue = kMaxAlpha;

    float lineToDrawY = self.headLineYPos;
    float lineWidth = kScanLineMaxWidth;
    float lineWidthStep = (kScanLineMaxWidth - kScanLineMinWidth) / (self.nbLines - 1);

    CGContextRef context = UIGraphicsGetCurrentContext();
    for (int i=1; i<=self.nbLines; i++) {

        CGContextBeginPath(context);
        CGContextSetLineWidth(context, lineWidth);
        CGContextSetStrokeColorWithColor(context, [self.scanColor colorWithAlphaComponent:alphaValue].CGColor);

        CGContextMoveToPoint(context, 0, lineToDrawY);
        CGContextAddLineToPoint(context, [self bounds].size.width, lineToDrawY);
        CGContextStrokePath(context);

        lineToDrawY -= kOneLineJumpDistance;

        lineWidth = MAX(0.5, lineWidth - lineWidthStep);
        alphaValue = MAX(0, alphaValue - alphaStep);
    }
}

self.nbLines may be around 30-40, may be 100.

But this part of the drawing is very time consuming and I'm not able to make a screen update each 2 or 3 ms. This is needed to ke开发者_如何学Cep the screen animation total time under a second (I move the head line each xxx ms by xxx pixels, but increasing this too much causes flickering).

How can I optimize this ?


If you are actually changing/animating every line segment and not just adding a segment to the end, then switching to using OpenGL ES for your drawing may be the only option that allows a high enough animation frame rate. On iOS devices, Open GL will render the polygons (lines) using GPU hardware rather than stroking lines in software as CG drawing does.

If you are only adding or changing the segments near the end, then a compositing approach may work (using multiple CALayers), where you don't re-render a large group of segments that don't change every frame.

Also, the max frame rate on iOS devices is 60 Hz, so you don't need to render more often the once every 16.6 mS. Re-rendering every 2 or 3 mS will be invisible to the display.


I think there is a possibility to use CoreAnimation if you can divide your picture into layers that only move over each other. AFAIK does the drawing then appear only once and the composing is done by the GPU.

Maybe you could draw the head line, which should be animated on a separate layer and then animate this layer using CoreAnimation.

I am not sure if that is helpful in any sense as I cannot imagine what you are drawing from the drawing code alone.


Unfortunately drawRect isn't the best place to do animations. I think the reason why is because the result of drawRect gets copied into a new texture (a CALayer) and then shown on the screen.

If the animation you want to do can't be accomplished with UIView animations or CoreAnimation something you can do are:

  1. Make sure you aren't calling needsDisplay on unnecessarily often. Once you draw something once, the result is cached in a CALayer so drawRect should only need to be called when something changes.

  2. Since you are making a view that updates a lot, try using needsDisplayInRect instead of needsDisplay. Then refactor your code to only update the portion passed in drawRect.

  3. If you still don't get the performance you need, you should look into drawing to the CGLayer directly or using a library like cocos2d

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜