2009-09-18 18 views
8

Estoy tratando de guardar y restaurar un CGContext para evitar hacer cálculos pesados ​​de dibujo por segunda vez y obtengo el error <Error>: CGGStackRestore: gstack underflow.Guardar y restaurar CGContext

¿Qué estoy haciendo mal? ¿Cuál es la forma correcta de hacer esto?

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

    if (initialized) { 
     CGContextRestoreGState(context); 
     //scale context 
     return; 
    } 

    initialized = YES; 

    //heavy drawing computation and drawing 

    CGContextSaveGState(context); 
} 

Respuesta

5

¿No quiere guardar primero y luego restaurar? Si está restaurando antes de guardar, no hay contexto para restaurar y obtendría un flujo inferior.

Aquí es la forma en que he utilizado:

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); 

o:

CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(context); 
    CGContextAddRect(context, originalRect); 
    CGContextClip(context); 

    [self drawInRect:rect]; 

    CGContextRestoreGState(context); 

Quizás esté tratando de hacer algo más.

+0

siento que he editado mi código y conseguir el mismo error de nuevo – cocoatoucher

17

Creo que puede estar malinterpretando lo que CGContextSaveGState() y CGContextRestoreGState() hacen. Impulsan el estado de gráficos actual en una pila y lo abren, permitiéndole transformar el espacio de dibujo actual, cambiar los estilos de línea, etc., y luego restaurar el estado a lo que era antes de establecer esos valores. No almacena elementos de dibujo, como caminos.

Desde el documentation on CGContextSaveGState():

Cada contexto gráfico mantiene una pila de los estados gráficos. Tenga en cuenta que no todos los aspectos del entorno de dibujo actual son elementos del estado de gráficos . Por ejemplo, la ruta actual no se considera parte de el estado de gráficos y, por lo tanto, no se guarda cuando se llama a la función CGContextSaveGState().

La pila estado de los gráficos se deben restablecer al comienzo de su drawRect:, razón por la que está recibiendo errores al intentar hacer estallar un estado de los gráficos de la pila. Como no habías empujado a ninguno, no había ninguno para explotar. Todo esto significa que no puede almacenar su dibujo como estado gráfico en la pila, y luego restaurarlo más tarde.

Si todo lo que le preocupa es el almacenamiento en caché de su dibujo, eso se hace por el CALayer que respalda su UIView (en el iPhone). Si todo lo que hace es mover su vista, no se volverá a dibujar. Solo se dibujará si se lo indica manualmente. Si tiene que actualizar parte del dibujo, le recomiendo dividir los elementos estáticos en sus propias vistas o CALayers para que solo se vuelva a dibujar la parte que cambia.

0

.. Según su código!, Parece que está restaurando el contexto antes de guardarlo. Primero lo primero:

  1. crear un contexto
  2. guardar su estado, también conocido como empuje
  3. hacer algunas cosas con el contexto
  4. Restaurar el contexto aka Pop
  5. regla general para cada Store(push) Debe ser Restore(pop)
  6. ¡Libere el contexto cuando haya terminado con esto!, Esto se refiere al contexto/s que tienen CGCreate, CGCopy,

Código de ejemplo:

 [super drawRect:rect]; 
     CGContextRef ctx = UIGraphicsGetCurrentContext(); 
// save context 
     CGContextSaveGState(ctx); 
// do some stuff 
     CGContextSetRGBStrokeColor(ctx, 1.0, 0.5, 0.5, 1.0); 
     // drawing vertical lines 
     CGContextSetLineWidth(ctx, 1.0); 
     for (int i = 0; i < [columns count]; i++) { 
      CGFloat f = [((NSNumber*) [columns objectAtIndex:i]) floatValue]; 
      CGContextMoveToPoint(ctx, f+(i*20.5), 0.5); 
      CGContextAddLineToPoint(ctx, f+(i*20.5), self.bounds.size.height); 
     } 
// restore context 
     CGContextRestoreGState(ctx); 
// do some other stuff 
     // drawing hozizontal lines 
     CGContextSetLineWidth(ctx, 1.0); 
     CGContextSetRGBStrokeColor(ctx, 0.12385, 0.43253, 0.51345, 1.0); 
     for (int i = 0; i < [columns count]; i++) { 
      CGFloat f = [((NSNumber*) [columns objectAtIndex:i]) floatValue]; 
      CGContextMoveToPoint(ctx, 0.5, f+(i*20.5)); 
      CGContextAddLineToPoint(ctx,self.bounds.size.width,f+(i*20.5)); 
     } 

     CGContextStrokePath(ctx); 
    } 
// No context CGContextRelease , since we never used CGContextCreate 
Cuestiones relacionadas