1

EDIT:

What I am trying to achieve is skip the call to firstDraw() the second time that drawRect is called. Reason for this is that in my real code I have got a lot of data points and lines to draw, so I thought thata if I recycle the previously drawn things I could optimize the performance. Is this possible at all with CoreGraphics?


I'd like to be able to perform multiple drawings on a UIView without having to re-draw what I have already drawn.

The code below will execute two draws at a time distance of 2.4 seconds. After the first call I use CGContextSaveGState to save the state. In the second call I retrieve the current graphic context and then add some lines. However this seem to fail as it appears that the previous context is lost.


What I get:

Here is what I get at the first draw call:

enter image description here

Here is what I get after the second call:

enter image description here

This instead is what I would like to get instead after the second call:

enter image description here


Here is the code:

import UIKit

class GraphView: UIView {

    var count : Int = 0

    override func drawRect(rect: CGRect) {
        if ( count == 0){
            firstDraw()
         NSTimer.scheduledTimerWithTimeInterval(2.4, target: self, selector: "setNeedsDisplay", userInfo: nil, repeats: false)
            count++
        }
        else{
            addLinesToDraw()
        }
    }

    func firstDraw(){
        // Drawing code
        let context = UIGraphicsGetCurrentContext()

        CGContextMoveToPoint(context, 50, 50);

        CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
        CGContextSetRGBFillColor(context, 0, 0.0, 0.0, 1.0);
        CGContextAddLineToPoint(context, 60, 60);
        CGContextMoveToPoint(context, 150, 150);
        CGContextAddLineToPoint(context, 110, 90);
        CGContextSetLineWidth(context, 2);
        CGContextStrokePath(context);

        // Draw a Point as a small square
        CGContextSetRGBStrokeColor(context, 0.5, 0.5, 0.5, 1.0);
        CGContextSetRGBFillColor(context, 0.5, 0.5, 0.5, 1.0);
        //NSLog(@"Drawing rect at point [x: %i, y: %i]", xPosition+resolution, pressureIntValue);
        CGContextFillRect(context, CGRectMake(0, 0, 10, 10));
        CGContextAddRect(context, CGRectMake(0, 0, 10, 10));
        CGContextStrokePath(context);

        CGContextSaveGState(context)
    }

    func addLinesToDraw(){
        // Drawing code
        let context = UIGraphicsGetCurrentContext()

        CGContextMoveToPoint(context, 30, 60);

        CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
        CGContextSetRGBFillColor(context, 0, 0.0, 0.0, 1.0);
        CGContextAddLineToPoint(context, 20, 20);
        CGContextMoveToPoint(context, 120, 250);
        CGContextAddLineToPoint(context, 110, 90);
        CGContextSetLineWidth(context, 2);
        CGContextStrokePath(context);

        // Draw a Point as a small square
        CGContextSetRGBStrokeColor(context, 0.5, 0.5, 0.5, 1.0);
        CGContextSetRGBFillColor(context, 0.5, 0.5, 0.5, 1.0);
        //NSLog(@"Drawing rect at point [x: %i, y: %i]", xPosition+resolution, pressureIntValue);
        CGContextFillRect(context, CGRectMake(20, 30, 10, 10));
        CGContextAddRect(context, CGRectMake(20, 30, 10, 10));
        CGContextStrokePath(context);

        CGContextSaveGState(context)

    }
}
mm24
  • 9,280
  • 12
  • 75
  • 170

2 Answers2

0

Each time you call drawRect:, you have to draw everything from scratch. So, in your case, you want to change your code to something like:

override func drawRect(rect: CGRect) {
    firstDraw()

    if ( count == 0){
     NSTimer.scheduledTimerWithTimeInterval(2.4, target: self, selector: "setNeedsDisplay", userInfo: nil, repeats: false)
        count++
    }
    else{
        addLinesToDraw()
    }
}

If you don't like this solution, you could always do all your drawing in a separate CGContext and blit it to the screen in your drawRect method.

Tim Kokesh
  • 879
  • 7
  • 10
  • Ok. What I am trying to achieve is skip the call to firstDraw() the second time that drawRect is called. Reason for this is that in my real code I have got a lot of data points and lines to draw, so I thought thata if I recycle the previously drawn things I could optimize the performance. Is this possible at all with CoreGraphics? – mm24 Jan 18 '16 at 18:37
0

Use UIGraphicsPushContext(context) instead of CGContextSaveGState(context) to make your context the current drawing context.

Difference described here: CGContextSaveGState vs UIGraphicsPushContext

Community
  • 1
  • 1
shpasta
  • 1,913
  • 15
  • 21