I'm trying to save and restore a CGContext to avoid doing heavy drawing computations for a second time and I'm getting the error <Error>: CGGStackRestore: gstack underflow
.
What am I doing wrong? What is the correct way to do this?
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
if (initialized) {
CGContextRestoreGState(context);
//scale context
return;
}
initialized = YES;
//heavy drawing computation and drawing
CGContextSaveGState(context);
}
I think you might be misinterpreting what CGContextSaveGState()
and CGContextRestoreGState()
do. They push the current graphics state onto a stack and pop it off, letting you transform the current drawing space, change line styles, etc., then restore the state to what it was before you set those values. It does not store drawing elements, like paths.
From the documentation on CGContextSaveGState():
Each graphics context maintains a stack of graphics states. Note that not all aspects of the current drawing environment are elements of the graphics state. For example, the current path is not considered part of the graphics state and is therefore not saved when you call the
CGContextSaveGState()
function.
The graphics state stack should be reset at the start of your drawRect:
, which is why you're getting errors when you try to pop a graphics state off the stack. Since you hadn't pushed one on, there was none to pop off. All of this means that you can't store your drawing as graphics state on the stack, then restore it later.
If all you are worried about is caching your drawing, that is done for you by the CALayer
that backs your UIView
(on the iPhone). If all you are doing is moving your view around, it won't be redrawn. It will only be drawn if you manually tell it to do so. If you do have to update part of the drawing, I recommend splitting the static elements off into their own views or CALayers
so that only the part that changes is redrawn.
Don't you want to Save first and then Restore? If you are restoring before a save, then there is no context to restore, and you'd get an underflow.
Here is the way I have used it:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextClipToRect(context, CGRectMake(stripe[i][8], stripe[i][9], stripe[i][10], stripe[i][11]));
CGContextDrawLinearGradient(context, gradient, CGPointMake(15, 5), CGPointMake(15, 25), 0);
CGContextRestoreGState(context);
or:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextAddRect(context, originalRect);
CGContextClip(context);
[self drawInRect:rect];
CGContextRestoreGState(context);
Maybe you are trying to do something else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With