2009-09-18 30 views
8

CGContextを保存して復元しようとしています。重度の描画計算を2回目にすることを避けるため、エラー<Error>: CGGStackRestore: gstack underflowが発生しています。CGContextの保存と復元

私は間違っていますか?これを行う正しい方法は何ですか?

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

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

    initialized = YES; 

    //heavy drawing computation and drawing 

    CGContextSaveGState(context); 
} 

答えて

5

最初に保存してから復元しませんか?保存する前に復元している場合、復元するコンテキストはなく、アンダーフローが発生します。

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

か::

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

    [self drawInRect:rect]; 

    CGContextRestoreGState(context); 

たぶん、あなたが何かをやろうとしている。ここ

は、私はそれを使用している方法です。

+0

私は私のコードを編集して、再び同じエラーを取得しました – cocoatoucher

17

CGContextSaveGState()CGContextRestoreGState()は何を誤解していると思いますか?現在のグラフィックステートをスタックにプッシュしてポップすると、現在の描画スペースを変換したり、ラインスタイルを変更したり、ステートを元に戻したりすることができます。パスのような描画要素は格納されません。 documentation on CGContextSaveGState()から

各グラフィックスコンテキストは、グラフィックス状態の スタックを維持しています。 現在の図面のすべての側面が、 環境ではなく、 グラフィックス状態の要素であることに注意してください。たとえば、 現在のパスは のグラフィックス状態の一部とは見なされないため、 CGContextSaveGState()関数を呼び出すと が保存されません。

グラフィックステートスタックは、drawRect:の先頭にリセットする必要があります。そのため、スタックからグラフィックス状態をポップしようとするとエラーが発生します。あなたが1つを押していないので、飛び出すことはありませんでした。これは、図面をグラフィックスの状態でスタックに保存しておいてから、後で復元することができないことを意味します。

あなたの描画がキャッシュされていることが心配ならば、UIView(iPhone版)をバックアップするCALayerによって完了します。あなたがしているすべてがあなたの周りを見回しているなら、それは再描画されません。あなたが手作業でそうするよう指示した場合にのみ描画されます。図面の一部を更新する必要がある場合は、静的要素を独自のビューに分割するか、または変更した部分のみを再描画するようにCALayersをお勧めします。

0

..あなたのコードに基づいて、 保存する前にコンテキストを復元しているようです。 最初まず:

  1. 別名コンテキスト
  2. を持ついくつかのものがそれぞれStore(push)そこになければならないためPop
  3. 一般的なルール別名コンテキストを復元してください
  4. を押し、その状態保存コンテキスト
  5. を作成します。 be Restore(pop)
  6. 完了したらコンテキストをリリースしてください!これは、それらが持っているコンテキストを参照していますCGCreateCGCopy

サンプルコード:

申し訳ありません
 [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 
関連する問題