Tanner Ewing
Tanner Ewing

Reputation: 337

UIView subclass redraw UIBezierPath without redrawing entire view

I have an application that allows the user to draw over an image in order to eventually crop it to the path drawn. Unfortunately though it is very slow. The reason is that it relies on [self setNeedsDisplay] in order to refresh the UIBezierPath, this causes the image to redraw as well and hinders performance. Is there a way to implement this without redrawing the UIImage on every call to setNeedsDisplay? Or a better way to implement the entire thing? All help is appreciated! Below is my UIView subclass:

#import "DrawView.h"

@implementation DrawView
{
    UIBezierPath *path;
}

- (id)initWithCoder:(NSCoder *)aDecoder // (1)
{
    if (self = [super initWithCoder:aDecoder])
    {
        [self setMultipleTouchEnabled:NO]; // (2)
        [self setBackgroundColor:[UIColor whiteColor]];
        path = [UIBezierPath bezierPath];
        [path setLineWidth:2.0];

    }
    return self;
}

- (void)drawRect:(CGRect)rect // (5)
{
    [self.EditImage drawInRect:self.bounds];
    [[UIColor blackColor] setStroke];
    [path stroke];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path moveToPoint:p];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p]; // (4)
    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesMoved:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

@end

Upvotes: 1

Views: 289

Answers (1)

chrissukhram
chrissukhram

Reputation: 2967

I had this issue as well in one of my apps - as you mentioned it is calling drawInRect which is causing the performance issues. The way I resolved it was by separating the background image view and the view that needs to be re-drawn multiple times into their own classes.

So in this instance you would create a class which will represent your background image and then add your "drawView" to that view with a transparent background. This way all of the drawing will be handled by drawView but the background image will remain static. Once the user is done drawing the background view can then crop itself based on the path provided by drawView.

Upvotes: 1

Related Questions