12 Stimmen

Speichern und Wiederherstellen von CGContext

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

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

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

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

    initialized = YES;

    //heavy drawing computation and drawing

    CGContextSaveGState(context);
}

20voto

Brad Larson Punkte 169275

Ich glaube, Sie interpretieren das, was Sie sagen, falsch. CGContextSaveGState() y CGContextRestoreGState() tun. Sie schieben den aktuellen Grafikstatus auf einen Stapel und heben ihn wieder auf, so dass Sie die aktuelle Zeichenfläche transformieren, Linienstile ändern usw. und dann den Zustand wiederherstellen können, der vor dem Setzen dieser Werte bestand. Es werden keine Zeichenelemente wie Pfade gespeichert.

Von der Dokumentation zu CGContextSaveGState() :

E Stapel von Grafikzuständen. Beachten Sie, dass nicht alle Aspekte der aktuellen Zeichenumgebung Umgebung sind Elemente des Grafikstatus sind. [ ] aktuelle Pfad wird nicht als Teil des des Grafikstatus und wird daher [ ] CGContextSaveGState() Funktion.

Der Grafikstatus-Stapel sollte zu Beginn Ihrer drawRect: Deshalb erhalten Sie Fehler, wenn Sie versuchen, einen Grafikstatus vom Stapel zu nehmen. Da Sie keinen auf den Stapel geschoben hatten, gab es auch keinen zu entfernen. All dies bedeutet, dass Sie Ihre Zeichnung nicht als Grafikstatus auf dem Stack speichern und später wiederherstellen können.

Wenn Sie sich nur um die Zwischenspeicherung Ihrer Zeichnung sorgen, wird das für Sie von der CALayer die Ihr UIView (auf dem iPhone). Wenn Sie Ihre Ansicht nur verschieben, wird sie nicht neu gezeichnet. Sie wird nur gezeichnet, wenn Sie dies manuell anweisen. Wenn Sie einen Teil der Zeichnung aktualisieren müssen, empfehle ich, die statischen Elemente in eigene Ansichten aufzuteilen oder CALayers so dass nur der Teil, der sich ändert, neu gezeichnet wird.

7voto

mahboudz Punkte 39008

Wollen Sie nicht erst speichern und dann wiederherstellen? Wenn Sie vor dem Speichern wiederherstellen, gibt es keinen Kontext zum Wiederherstellen, und Sie würden einen Unterlauf erhalten.

Ich habe es folgendermaßen verwendet:

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

Vielleicht versuchen Sie, etwas anderes zu tun.

0voto

abdimuna Punkte 765

.. Basierend auf Ihrem Code !, Es scheint, dass Sie den Kontext vor dem Speichern wiederherstellen. Das Wichtigste zuerst:

  1. Einen Kontext erstellen
  2. Sichern des Status, auch Push genannt
  3. Machen Sie etwas mit dem Kontext
  4. Wiederherstellung des Kontexts aka Pop
  5. Allgemeine Regel für jede Store(push) muss es sein Restore(pop)
  6. Geben Sie den Kontext frei, wenn Sie damit fertig sind !, Dies bezieht sich auf den/die Kontext/e, die sie haben CGCreate , CGCopy ,

Beispiel-Code:

        [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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X