Undo using multitouch drawing in iOS

I am working with multitouch while writing. Therefore, basically I do this, I write with hand support, because, as a rule, its user rights, I followed this link How to ignore certain UITouch points in a multitouch sequence

Everything works fine, but their problem is with the cancellation, when I write by hand, touching the screen, otherwise it works fine.

Below is my code

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* topmostTouch = self.trackingTouch; for (UITouch *touch in touches) { ctr = 0; touchStartPoint1 = [touch locationInView:self]; [m_undoArray removeAllObjects]; [m_redoArray removeAllObjects]; [m_parentRedoArray removeAllObjects]; if(!topmostTouch || [topmostTouch locationInView:self].y > touchStartPoint1.y) { topmostTouch = touch; pts[0] = touchStartPoint1; } } if (self.trackingTouch != nil && self.trackingTouch != topmostTouch) // ![touches containsObject:self.trackingTouch]) { [self discardDrawing]; } self.trackingTouch = topmostTouch; } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if(self.trackingTouch== nil) { return; } CGPoint p = [self.trackingTouch locationInView:self]; ctr++; pts[ctr] = p; if (ctr == 4) { pts[3] = midPoint(pts[2], pts[4]); self.currentPath = [[DrawingPath alloc] init]; [self.currentPath setPathColor:self.lineColor]; self.currentPath.pathWidth = [NSString stringWithFormat:@"%f",self.lineWidth]; [self.currentPath.path moveToPoint:pts[0]]; [self.currentPath.path addCurveToPoint:pts[3] controlPoint1:pts[1] controlPoint2:pts[2]]; CGPathRef cgPath = self.currentPath.path.CGPath; mutablePath = CGPathCreateMutableCopy(cgPath); [m_undoArray addObject:self.currentPath]; [self setNeedsDisplay]; pts[0] = pts[3]; pts[1] = pts[4]; ctr = 1; } } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { if(touch == self.trackingTouch) { [m_parentUndoArray addObject:[NSArray arrayWithArray:m_undoArray]]; } } } -(void)undoButtonClicked { NSMutableArray *undoArray = [m_parentUndoArray lastObject]; NSLog(@"%@",undoArray); [m_parentUndoArray removeLastObject]; [m_parentRedoArray addObject:undoArray]; m_drawStep = UNDO; [self setNeedsDisplay]; } - (void)drawRect { I have different cases here, I am showing Of Undo for(int i = 0; i<[m_parentUndoArray count];i++) { NSMutableArray *undoArray = [m_parentUndoArray objectAtIndex:i]; NSLog(@"%@",undoArray); for(int i =0; i<[undoArray count];i++) { DrawingPath *drawPath = [undoArray objectAtIndex:i]; GPathRef path = drawPath.path.CGPath; mutablePath = CGPathCreateMutableCopy(path); //Draw into CgLayer } } } 

Here is an image to better understand my problem, I wrote this first

enter image description here

After clicking on undo Once

After clicking on Undo once, you can see above that the other part was canceled, not the last part. Therefore, I need help in this regard.

+2
ios uikit nsmutablearray core-graphics undo-redo
Feb 21
source share
2 answers

m_redoArray seems to be the big dad you are drawing from. I don’t understand why you empty it in "touchhesBegan ...", of course, one of these arrays should be carried through Began without changes, or will you discard the material from the very beginning of your drawing to the end, no?

It seems to me that this is how you dropped Hell in your example here.

+1
Feb 21 '14 at 20:18
source share

Well, in my case, I used bezierPath to draw to the touch and successfully implemented undo functionality. Here is the code:

 - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.backgroundColor = [UIColor clearColor]; myPath = [[UIBezierPath alloc] init]; myPath.lineCapStyle = kCGLineCapRound; myPath.miterLimit = 0; bSize=5; myPath.lineWidth = bSize; brushPattern = [UIColor whiteColor]; // Arrays for saving undo-redo steps in arrays pathArray = [[NSMutableArray alloc] init]; bufferArray = [[NSMutableArray alloc] init]; } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { [brushPattern setStroke]; for (id path in pathArray){ if ([path isKindOfClass:[UIBezierPath class]]) { UIBezierPath *_path=(UIBezierPath *)path; [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; } } } #pragma mark - Touch Methods -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *mytouch = [[touches allObjects] objectAtIndex:0]; myPath = [[UIBezierPath alloc] init]; myPath.lineWidth = bSize; [myPath moveToPoint:[mytouch locationInView:self]]; [pathArray addObject:myPath]; } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [myPath addLineToPoint:[[touches anyObject] locationInView:self]]; [self setNeedsDisplay]; } #pragma mark - Undo Method -(void)undoButtonClicked { if([pathArray count]>0) { UIBezierPath *_path = [pathArray lastObject]; [bufferArray addObject:_path]; [pathArray removeLastObject]; [self setNeedsDisplay]; } } -(void)setBrushSize: (CGFloat)brushSize { bSize=brushSize; } -(void)redoButtonClicked { if([bufferArray count]>0){ UIBezierPath *_path = [bufferArray lastObject]; [pathArray addObject:_path]; [bufferArray removeLastObject]; [self setNeedsDisplay]; } } 

Hope this helps you.

0
Feb 21 '14 at 2:04
source share



All Articles