Search code examples
iphoneiosuicolor

Using UIGraphicsPushContext(context) and UIGraphicsPopContext()


Very frustrating experience understanding UIGraphicsPushContext(context) and UIGraphicsPopContext()

My understanding is that I can set attributes of the context like the stroke color and then push the context on a stack so I can set a new color for the current context. When I'm done doing that I can return to the context by popping it.

Below is my code. When I run the code below two lines are drawn in blue. What I expect to happen is: that I first set the color green. Go to the blueLine function and push the green context. Draw in blue. Then pop the green context. Allowing the drawLine function to drawn in green.

Here is a screenshot of what is drawn (two blue lines): http://dl.dropbox.com/u/1207310/iOS%20Simulator%20Screen%20shot%20Feb%205%2C%202012%209.00.35%20PM.png

Any help is GREATLY appreciated! Thank you.

- (void)drawBlueLine:(CGContextRef)context
{
    UIGraphicsPushContext(context);
    [[UIColor blueColor] setStroke];
    CGContextBeginPath(context);
    CGContextMoveToPoint(context, self.bounds.origin.x, 100);
    CGContextAddLineToPoint(context, self.bounds.origin.x+self.bounds.size.width, 200);
    CGContextStrokePath(context); 
    UIGraphicsPopContext();
}

- (void)drawLine:(CGContextRef)context
{
    UIGraphicsPushContext(context);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context, self.bounds.origin.x, 200);
    CGContextAddLineToPoint(context, self.bounds.origin.x+self.bounds.size.width, 300);
    CGContextStrokePath(context); 
    UIGraphicsPopContext();
}

- (void)drawRect:(CGRect)rect
{   
    CGContextRef context = UIGraphicsGetCurrentContext();

    [[UIColor redColor] setStroke];
    CGContextSetLineWidth(context, 5.0);
    [self drawBlueLine:context];
    [self drawLine:context];
}

Or shouldn't this work?

- (void)drawLine:(CGContextRef)oldContext
{

    UIGraphicsPushContext(oldContext); //makes oldContext the current context but there is a copy on the stack
    [[UIColor blueColor] setStroke];
    CGContextBeginPath(oldContext);
    CGContextMoveToPoint(oldContext, self.bounds.origin.x, 200);
    CGContextAddLineToPoint(oldContext, self.bounds.origin.x+self.bounds.size.width, 300);
    CGContextStrokePath(oldContext); 

    UIGraphicsPopContext(); //previous oldContext is moved back into place containing red?
}

- (void)drawRect:(CGRect)rect
{ 

    CGContextRef oldContext = UIGraphicsGetCurrentContext();

    [[UIColor redColor] setStroke];
    [self drawLine:oldContext];
    //anything I draw here should be red.  Shouldn't it?`

Solution

  • What UIGraphicsPushContext and UIGraphicsPopContext does as change which context is being used for drawing, not necessarily save and restore any given context's state. What your code is doing is simply repetitively replacing the context that was current prior to the call to drawRect: with the context you grab with UIGraphicsGetCurrentContext (they are likely to be the same anyway).

    If you want to save an restore a given context's state, use CGContextSaveGState and CGContextRestoreGState instead.