2009-09-18 15 views
8

Sto cercando di salvare e ripristinare un CGContext per evitare di fare calcoli di disegno pesanti per la seconda volta e sto ottenendo l'errore <Error>: CGGStackRestore: gstack underflow.Salvataggio e ripristino CGContext

Cosa sto sbagliando? Qual è il modo corretto per farlo?

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

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

    initialized = YES; 

    //heavy drawing computation and drawing 

    CGContextSaveGState(context); 
} 

risposta

5

Non si desidera salvare prima e quindi ripristinare? Se esegui il ripristino prima di un salvataggio, non c'è un contesto da ripristinare e otterrai un underflow.

Ecco il modo in cui ho usato:

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

Forse si stanno cercando di fare qualcosa di diverso.

+0

dispiace Ho modificato il mio codice e ottenere di nuovo lo stesso errore – cocoatoucher

17

penso che si potrebbe essere erroneamente interpretato ciò CGContextSaveGState() e CGContextRestoreGState() fanno. Spingono lo stato grafico corrente in uno stack e pop fuori, che ti permette di trasformare lo spazio disegno corrente, stili di linea del cambiamento, ecc, quindi ripristinare lo stato a quello che era prima di impostare questi valori. Non memorizza elementi di disegno, come i percorsi.

Dal documentation on CGContextSaveGState():

Ogni contesto grafico mantiene un pila di stati di grafica. Si noti che non tutti gli aspetti del contesto attuale disegno sono elementi dello stato grafica. Ad esempio, il percorso corrente non è considerato parte dello stato grafico ed è pertanto non salvato quando si chiama la funzione CGContextSaveGState().

la grafica pila Stato deve essere resettato all'inizio del vostro drawRect:, ed è per questo che stai ricevendo gli errori quando si tenta di pop uno stato grafica dallo stack. Dal momento che non ne avevi premuto uno, non c'era nessuno da far uscire. Tutto ciò significa che non è possibile memorizzare il disegno come stato grafico nello stack, quindi ripristinarlo in un secondo momento.

Se tutto ciò che ti preoccupa è il caching del tuo disegno, questo è fatto per te dal CALayer che supporta il tuo UIView (su iPhone). Se tutto ciò che stai facendo è spostare la tua vista, non verrà ridisegnata. Sarà disegnato solo se glielo comunichi manualmente. Se c'è bisogno di aggiornare parte del disegno, vi consiglio la scissione degli elementi statici fuori nelle proprie opinioni o CALayers in modo che solo la parte che cambia è ridisegnato.

0

.. Sulla base della sua codice!, Sembra che si sta ripristinando il contesto prima di salvarlo. Per prima cosa:

  1. Creare un contesto
  2. salvare il suo stato, alias spingere
  3. fare alcune cose con il contesto
  4. ripristinare il contesto di alias Pop
  5. Regola generale per ogni Store(push) ci deve be Restore(pop)
  6. Rilasciare il contesto quando hai finito!, Si riferisce a quei/e contesto/i che hanno CGCreate, CGCopy,

codice di esempio:

 [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 
Problemi correlati