2009-09-18 11 views
8

Ich versuche, einen CGContext zu speichern und wiederherzustellen, um zu vermeiden, schwere Zeichnung Berechnungen ein zweites Mal zu tun, und ich bekomme den Fehler <Error>: CGGStackRestore: gstack underflow.Speichern und Wiederherstellen von CGContext

Was mache ich falsch? Was ist der richtige Weg, dies zu tun?

Antwort

5

Wollen Sie nicht zuerst speichern und dann wiederherstellen? Wenn Sie vor einem Speichervorgang wiederherstellen, gibt es keinen wiederherzustellenden Kontext und Sie erhalten einen Unterlauf.

Hier ist die Art, wie ich es benutzt haben:

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

oder:

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

    [self drawInRect:rect]; 

    CGContextRestoreGState(context); 

Sie versuchen, etwas anderes Vielleicht zu tun.

+0

leid, dass ich wieder meinen Code und immer den gleichen Fehler bearbeitet haben – cocoatoucher

17

Ich denke, Sie könnten falsch interpretieren, was CGContextSaveGState() und CGContextRestoreGState() tun. Sie schieben den aktuellen Grafikzustand auf einen Stapel und entfernen ihn, um den aktuellen Zeichenbereich zu transformieren, Linienstile zu ändern usw. und dann den Zustand wiederherzustellen, der vor dem Festlegen dieser Werte vorlag. Zeichnungselemente wie Pfade werden nicht gespeichert.

Vom documentation on CGContextSaveGState():

Jeder Grafikkontext unterhält einen Stapel von Grafiken Staaten. Beachten Sie, dass nicht alle Aspekte der aktuellen Zeichnung Umgebung sind Elemente des Grafikstatus. Zum Beispiel wird der Strompfad nicht als Teil von des Grafikstatus betrachtet und daher nicht gespeichert, wenn Sie die CGContextSaveGState() Funktion aufrufen.

Der Grafikzustand Stapel sollte am Anfang Ihrer drawRect: zurückgesetzt werden, weshalb Sie ist es, Fehler bekommen, wenn Sie versuchen, eine Grafikzustand vom Stapel Pop. Da du es nicht weitergeschoben hast, gab es keins, das abspringen könnte. All dies bedeutet, dass Sie Ihre Zeichnung nicht als Grafikstatus auf dem Stapel speichern und später wiederherstellen können.

Wenn Sie nur besorgt sind, ist das Zwischenspeichern Ihrer Zeichnung, die für Sie von der CALayer, die Ihre UIView (auf dem iPhone) unterstützt. Wenn Sie nur Ihre Ansicht verschieben, wird sie nicht neu gezeichnet. Es wird nur gezeichnet, wenn Sie es manuell dazu sagen. Wenn Sie einen Teil der Zeichnung aktualisieren müssen, empfehle ich, die statischen Elemente in ihre eigenen Ansichten zu zerlegen oder CALayers, so dass nur der Teil, der sich ändert, neu gezeichnet wird.

0

.. Basierend auf Ihrem Code!, Es scheint, dass Sie den Kontext wiederherstellen, bevor Sie es speichern. Das allererste:

  1. erstellen Kontext
  2. seinen Zustand speichern, auch bekannt als Push
  3. ein paar Sachen mit dem
  4. Kontext Do
  5. Wiederherstellen der Kontext aka Pop
  6. Allgemeine Regel für jeden Store(push) da muss be Restore(pop)
  7. Geben Sie den Kontext frei, wenn Sie damit fertig sind! Dies bezieht sich auf die Kontext/s, die sie haben CGCreate, CGCopy,

Beispielcode:

 [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