2009-09-18 10 views
8

Próbuję zapisać i przywrócić CGContext, aby uniknąć wykonywania ciężkich obliczeń po raz drugi i otrzymuję komunikat o błędzie <Error>: CGGStackRestore: gstack underflow.Zapisywanie i przywracanie CGContext

Co robię źle? Jaki jest prawidłowy sposób to zrobić?

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

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

    initialized = YES; 

    //heavy drawing computation and drawing 

    CGContextSaveGState(context); 
} 

Odpowiedz

5

Nie chcesz najpierw zapisać, a potem przywrócić? Jeśli odtwarzasz przed zapisaniem, nie ma kontekstu do przywrócenia, a otrzymasz niedopełnienie.

Oto sposób użyłem go:

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

czyli

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

    [self drawInRect:rect]; 

    CGContextRestoreGState(context); 

Może starają się zrobić coś innego.

+0

przepraszam mam edytowane mój kod i znowu się ten sam błąd – cocoatoucher

17

Myślę, że możesz źle zrozumieć, co robią CGContextSaveGState() i CGContextRestoreGState(). Przesuwają bieżący stan grafiki na stos i wyrzucają go, umożliwiając przekształcenie aktualnej przestrzeni rysunkowej, zmianę stylów linii itp., A następnie przywrócenie stanu do stanu przed ustawieniem tych wartości. Nie przechowuje elementów rysunku, takich jak ścieżki.

Z documentation on CGContextSaveGState():

Każdy kontekst graficzny utrzymuje stos stanów graficznych. Zauważ, że nie wszystkie aspekty bieżącego rysunku są elementami stanu grafiki . Na przykład ścieżka prądu nie jest częścią stanu grafiki i dlatego nie jest zapisywana podczas wywoływania funkcji CGContextSaveGState().

Grafiki stan stosu należy zresetować na początku twojej drawRect:, dlatego dostajesz błędy podczas próby pop stan grafiki ze stosu. Ponieważ nie wepchnąłeś jednego, nie było nikogo, kto by się wyskoczył. Wszystko to oznacza, że ​​nie można zapisać rysunku jako stanu graficznego na stosie, a następnie przywrócić go później.

Jeśli martwisz się tylko o buforowanie rysunku, zrobisz to za pomocą CALayer, który wykona kopię twojego UIView (na iPhonie). Jeśli wszystko, co robisz, porusza twój widok, nie zostanie przerysowane. Będzie narysowany tylko wtedy, gdy ręcznie to powiesz. Jeśli musisz zaktualizować część rysunku, zalecam podzielenie elementów statycznych na ich własne widoki lub CALayers, tak aby przerobić tylko część, która się zmienia.

0

.. Na podstawie Twojego kodu!, Wygląda na to, że przywracasz kontekst przed zapisaniem go. First Thing pierwsze:

  1. Tworzenie kontekstu
  2. Zapisz swój stan, aka naciskać
  3. Czy jakieś rzeczy z kontekstu
  4. Restore kontekst aka Pop
  5. Zasada ogólna dla każdej Store(push) musi być Restore(pop)
  6. Zwolnij kontekst, gdy skończysz!, To odnosi się do kontekstu/ów, które mają CGCreate, CGCopy,

Przykładowy kod:

 [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