undo redo issues with CGLayer

I am working with unod redo operations on CgLayer, I have tried some code, but not able to get it working, dont know , where I am getting wrong, below is my code, which i have written

this is my drawRect function

  • Alternatives to dispatch_get_current_queue() for completion blocks in iOS 6?
  • The operation couldn’t be completed. (Cocoa error 260.)
  • How to get iPhone SDK 2.2.1 for Xcode 3.2?
  • Converting wildcard bundle identifier to single ID
  • Why can't I register my iOS application to handle the image file type?
  • Why doesn't this code produce the correct output?
  • - (void)drawRect:(CGRect)rect
        m_backgroundImage = [UIImage imageNamed:@"bridge.jpg"];
        CGPoint drawingTargetPoint = CGPointMake(0,0);
        [m_backgroundImage drawAtPoint:drawingTargetPoint];
              case DRAW:
                  CGContextRef context = UIGraphicsGetCurrentContext();
                  if(myLayerRef == nil)
                      myLayerRef = CGLayerCreateWithContext(context, self.bounds.size, NULL);
                  CGContextDrawLayerAtPoint(context, CGPointZero, myLayerRef); 
             case UNDO:
                  [curImage drawInRect:self.bounds];              

    On touches ended , I am converting the layer into NSValue and storing as keyValue pair into NSDictionary and then adding the dictionary object to array.

    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
        NSValue *layerCopy = [NSValue valueWithPointer:myLayerRef];
        NSDictionary *lineInfo = [NSDictionary dictionaryWithObjectsAndKeys:layerCopy, @"IMAGE",
        [m_pathArray addObject:lineInfo];    
        NSLog(@"%i",[m_pathArray count]);

    below is my Undo functionality

    - (void)undoButtonClicked
        if([m_pathArray count]>0)
            NSMutableArray *_line=[m_pathArray lastObject];
            [m_bufferArray addObject:[_line copy]];
            [m_pathArray removeLastObject];
            drawStep = UNDO;
            [self redrawLine];
    //Redraw functions
    - (void)redrawLine
        NSDictionary *lineInfo = [m_pathArray lastObject];
        NSValue *val = [lineInfo valueForKey:@"IMAGE"];
        CGLayerRef  layerToShow = (CGLayerRef) [val pointerValue];
        CGContextRef context1 = CGLayerGetContext(layerToShow);
        CGContextDrawLayerAtPoint(context1, CGPointMake(00, 00),layerToShow);
        [self setNeedsDisplayInRect:self.bounds];

    I think its here where I am goin wrong. So friends please help me out.

    From the comments below, I have added the function, where its draws into Cglayer(this function I am calling into touchesMovedEvent.

    - (void) drawingOperations
        CGContextRef context1 = CGLayerGetContext(myLayerRef);    
        CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); 
        CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);     
        CGContextMoveToPoint(context1, mid1.x, mid1.y);
        CGContextAddQuadCurveToPoint(context1, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y); 
        CGContextSetLineCap(context1, kCGLineCapRound);
        CGContextSetLineWidth(context1, self.lineWidth);
        CGContextSetStrokeColorWithColor(context1, self.lineColor.CGColor);           
        CGContextSetAllowsAntialiasing(context1, YES);
        CGContextSetInterpolationQuality(context1, kCGInterpolationHigh); 
        CGContextSetAlpha(context1, self.lineAlpha);


    2 Solutions Collect From Internet About “undo redo issues with CGLayer”

    The best way to implement Undo and Redo is to implement NSUndoManager as a brief description of it you don’t have to save each state of Object that you want to undo or redo the NSUndoManager itself make this for you …

    Steps for reaching this is:

    1- Initialize NSUndoManager.

    2- Register Object state in the NSUndoManager object with specified function call will discuss this for you case later.

    3-use undo or redo or clear actions function in NSUndoManager Object.

    Ex from my working solution

    -in .h file

    @property (nonatomic,retain) NSUndoManager *undoManager;
    • in .m file

      @synthesize undoManager;

    • in “viewDidLoad” method — initialize your NSUndoManager

      undoManager = [[NSUndoManager alloc] init];

    Suppose that you have a function in your class that zoom in/out using pinch so in your “viewDidLoad” you will have

    UIPinchGestureRecognizer *pinchGesture =
        [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
        pinchGesture.delegate = (id)self;
        [self.view addGestureRecognizer:pinchGesture];

    So pinch will zoom in/out such
    Note that “MyImageView” is the image that we want to zoom in/out

    - (void)pinch:(UIPinchGestureRecognizer*)recognizer{
        if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateChanged) {
            NSLog(@"gesture.scale = %f", recognizer.scale);
            CGFloat currentScale = self.MyImageView.frame.size.width / self.MyImageView.bounds.size.width;
            CGFloat newScale = currentScale * recognizer.scale;
            //Here is the line that register image to NSUndoManager before making and adjustments to the image "save current image before changing the transformation"
            //Add image function is function that fired when you Make undo action using NSUndoManager "and so we maintain only image transformation that changed when you zoom in/out"
             [[undoManager prepareWithInvocationTarget:self] AddImage:self.MyImageView.transform];
            if (newScale < 0.5) {
                newScale = 0.5;
            if (newScale > 5) {
                newScale = 5;
            CGAffineTransform transform = CGAffineTransformMakeScale(newScale, newScale);
            self.MyImageView.transform = transform;
            recognizer.scale = 1;

    -AddImage Function will save current image transformation state in NSUndoManager.

        CGAffineTransform transform = sender;
        self.MyImageView.transform = transform;

    So if you have button that make Undo action

      if ([undoManager canUndo]) {
          [undoManager undo];

    So if you want to cancel all action you have both ways

    while ([undoManager canUndo]) {
       [undoManager undo];


    [undoManager removeAllActions];
    • (void)redrawLine
      NSDictionary *lineInfo = [m_pathArray lastObject];

      NSValue *val = [lineInfo valueForKey:@”IMAGE”];

      CGContextRef context1 = (CGContextRef) [val pointerValue];
      CGContextDrawLayerAtPoint(context1, CGPointMake(00, 00),layerToShow);
      [self setNeedsDisplayInRect:self.bounds];

    just update this method with ur code