Undo/Redo for drawing in iOS

寵の児 提交于 2019-11-27 09:36:34
Ranjit

I have found a solution for this, we need to create a array of array of DrawingPaths:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
   // Do the above code, then
   [m_undoArray addObject:self.currentPath];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
   [m_parentUndoArray addObject:[NSArray arrayWithArray:m_undoArray]];
}

and then stroke the path in DrawRect.

If your drawRect method can draw whatever CGPaths are in the array, all you need to do is trigger the drawing again in you Undo method by calling setNeedsDisplay after you have removed the last added CGPath

I think you're making more path objects than you intend. I suggest go to where you alloc the bezierPath in touches moved and replace

self.currentPath = [[DrawingPath alloc] init];

With

if(!self.currentPath){
                    self.currentPath = [[DrawingPath alloc] init];
}

Well You should be doing it this way as its easy

- (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)
    {
        if ([[pathArray lastObject] isKindOfClass:[SPUserResizableView class]])
        {
            [[pathArray lastObject] removeFromSuperview];
        }  
    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];
    }
}
 -(void)undoAllButtonClicked
{
  [pathArray removeAllObjects];
  [self setNeedsDisplay];
}

Hope it will help.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!