Fighting the problem since many days. I hope I get an answer here. I used this link to smooth my drawing in my free hand. In this code, I managed to set the width and color of the line, but I find it difficult to do this when I try to include the undo / redo function in it using this , which works great when undoing the redo, but its free manual training is not smooth.
After some research and coding, I should know that this is a drawing cutting which, I think, prevents undo / redo.
The first link contains the file "CachedLIView.h / m", when I used this and try to include undo / redo in it, I found that in the following method:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
this method calls the drawBitMap method: a method that actually generates a temporary image each time the user lifts his finger and at the same time removes points from the "path".
- (void)drawBitmap // (3) { UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0); [[UIColor blackColor] setStroke]; if (!incrementalImage) // first draw; paint background white by ... { UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object [[UIColor greenColor] setFill]; [rectpath fill]; // filling it with white } [incrementalImage drawAtPoint:CGPointZero]; //[path stroke]; for (UIBezierPath *_path in pathArray) [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; incrementalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); }
I save each path in an array so that I can undo / redo. (took this idea from the second link).
The following is the full code for this file, which I modified to include undo / redo:
#import "CachedLIView.h" @implementation CachedLIView { UIBezierPath *path; UIImage *incrementalImage; // (1) } - (id)initWithFrame:(CGRect)frame // (1) { if (self = [super initWithFrame:frame]) { [self setMultipleTouchEnabled:NO]; // (2) // [self setBackgroundColor:[UIColor whiteColor]]; // path = [[UIBezierPath alloc] init]; // [path setLineWidth:3]; pathArray=[[NSMutableArray alloc]init]; bufferArray=[[NSMutableArray alloc]init]; [self drawBitmap]; } return self; } - (void)drawRect:(CGRect)rect { NSLog(@"in drawrect pathArray[count]: %d", pathArray.count); [incrementalImage drawInRect:rect]; // (3) //[[UIColor blackColor] setStroke]; //[path stroke]; for (UIBezierPath *_path in pathArray) [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { path = [[UIBezierPath alloc] init]; path.lineWidth = 3; UITouch *touch = [touches anyObject]; CGPoint p = [touch locationInView:self]; [path moveToPoint:p]; [pathArray addObject:path]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint p = [touch locationInView:self]; [path addLineToPoint:p]; [self setNeedsDisplay]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2) { UITouch *touch = [touches anyObject]; CGPoint p = [touch locationInView:self]; [path addLineToPoint:p]; [self drawBitmap]; // (3) [self setNeedsDisplay]; [path removeAllPoints]; //(4) } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [self touchesEnded:touches withEvent:event]; } - (void)drawBitmap // (3) { UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0); [[UIColor blackColor] setStroke]; if (!incrementalImage) // first draw; paint background white by ... { UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object [[UIColor greenColor] setFill]; [rectpath fill]; // filling it with white } [incrementalImage drawAtPoint:CGPointZero]; //[path stroke]; for (UIBezierPath *_path in pathArray) [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; incrementalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); }
.h file:
Please help me. What am I doing wrong. The pathArray counter is working correctly. but cannot show the cancel / redo effect on the screen.