开发者

QuartzCore performance on clear UIView

I have a UIView where I set the background color to clear in the init method. I then draw a blue line between 2 points in drawRect. The first point is the very first touch on the view, and the second point is changed when touchesMoved is called.

So that one end of the line is fixed, and the other end moves with the users finger. However when the backgroundcolor is clear the line has quite a big of delay and skips (is not smooth).

If I change the background color to black (just uncommenting the setbackgroundcolor line) then the movement is much smoother and it looks great, apart from you can't see the views behind it.

How can I solve this issue? (on the iPad, I only have the simulator, and haven't currently got access to a device) So that the performance is smooth, but the background is clear so you can see the background views.

-(id) initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        //self.backgroundColor = [UIColor clearColor];
    }
    ret开发者_如何学Curn self;
}

-(void) drawRect:(CGRect)rect {
if (!CGPointEqualToPoint(touchPoint, CGPointZero)) {
    if (touchEnded) {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextClearRect(context, rect);
    } else {

CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, rect);
    CGContextSetLineWidth(context, 3.0f);
    CGFloat blue[4] = {0.0f, 0.659f, 1.0f, 1.0f};
    CGContextSetAllowsAntialiasing(context, YES);
    CGContextSetStrokeColor(context, blue);
    CGContextMoveToPoint(context, startPoint.x, startPoint.y);
    CGContextAddLineToPoint(context, touchPoint.x, touchPoint.y);
    CGContextStrokePath(context);

    CGContextSetFillColor(context, blue);

    CGContextFillEllipseInRect(context, CGRectMakeForSizeAroundCenter(CGSizeMake(10, 10), touchPoint));
    CGContextFillEllipseInRect(context, CGRectMakeForSizeAroundCenter(CGSizeMake(10, 10), startPoint));
    }   
    }
}



-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    self.touchEnded = NO;
    if ([[touches allObjects] count] > 0) 
        startPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self];
        touchPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self];
    [self setNeedsDisplay];
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    self.touchEnded = NO;
    if ([[touches allObjects] count] > 0) 
        touchPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self];
    [self setNeedsDisplay];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    self.touchEnded = YES;
    [self setNeedsDisplay];
    [self removeFromSuperview];
}
- (void)dealloc {
    [super dealloc];
}


First of all, you should test performance on a device, rather than in Simulator. Most of graphics-related stuff works very differently in Simulator, some being much faster and some, surprisingly, much slower.

That said, if a transparent background does prove to be a performance problem on a device, it's most likely because you fill too many pixels with CGContextClearRect(). I can think of two solutions off the top of my head:

  • In touchesBegan:withEvent: you can make a snapshot of the underlying view(s) using CALayer's renderInContext: method and draw the snapshot as the background instead of clearing it. That way you can leave the view opaque and thus save time on compositing the view with views underneath it.
  • You can create a one-point-tall CALayer representing a line and transform it in touchesMoved:withEvent: so that its ends are in correct positions. Same goes for dots representing the line ends (CAShapeLayer is great for that). There will be some ugly trigonometry involved, but the performance is going to be excellent.
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜