2009-08-18 5 views
0

これはかなり簡単な例であり、おそらく、とにかく違いの多くを作るが、私はグラデーションを描画するビューで、この描画コードを持って言うだろう:-drawRectの一般的な操作をiPhoneにキャッシュする必要はありますか?

@interface SomeView : UIView 
@end 

@implementation SomeView 

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

    // Set fill color to white 
    CGContextSetGrayFillColor(ctx, 1.0f, 1.0f); 
    CGContextFillRect(ctx, rect); 

    // Create a fancy, albeit ugly, orange gradient 
    const CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    const CGFloat components[] = { 1.0, 0.5, 0.4, 1.0, // Start color 
            0.8, 0.8, 0.3, 1.0 }; // End color 
    CGGradientRef gloss; 
    gloss = CGGradientCreateWithColorComponents(rgbColorSpace, components, NULL, 2); 
    CGColorSpaceRelease(rgbColorSpace); 

    // Draw the gradient 
    const CGPoint endPoint = {rect.origin.x, 
           rect.origin.y + floor(rect.size.height/2.0f)}; 
    CGContextDrawLinearGradient(ctx, gloss, rect.origin, endPoint, 0); 
    CGGradientRelease(gloss); 
} 

@end 

私は、これは非常に無視できる例であると認識しかし、私が再利用するより複雑な値を持っていれば、その懸念を想像することができます。これらをキャッシュする必要がありますか、またはCocoa-Touchは本質的にCALayersでそれを行いますか?

は、ここで私は、キャッシングによって何を意味するかの例です:

@interface SomeView : UIView 
{ 
    CGGradientRef gloss; 
} 
@end 

@implementation SomeView 

- (id)initWithFrame:(CGRect)frame 
{ 
    if (self = [super initWithFrame:frame]) { 
     // Create a fancy, albeit ugly, orange gradient only once here instead 
     const CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
     const CGFloat components[] = { 1.0, 0.5, 0.4, 1.0, // Start color 
             0.8, 0.8, 0.3, 1.0 }; // End color 
     CGGradientRef gloss; 
     gloss = CGGradientCreateWithColorComponents(rgbColorSpace, components, NULL, 2); 
     CGColorSpaceRelease(rgbColorSpace); 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    CGGradientRelease(gradient); 
    [super dealloc]; 
} 

- (void)drawRect:(CGRect) 
{ 
    const CGContextRef ctx = UIGraphicsGetCurrentContext(); 

    // Set fill color to white 
    CGContextSetGrayFillColor(ctx, 1.0f, 1.0f); 
    CGContextFillRect(ctx, rect); 

    // Draw the gradient 
    const CGPoint endPoint = {rect.origin.x, 
           rect.origin.y + floor(rect.size.height/2.0f)}; 
    CGContextDrawLinearGradient(ctx, gloss, rect.origin, endPoint, 0); 
} 

@end 

あなたは明らかに、ここでのトレードオフを見ることができます。特に私がこれらの見解をたくさん持っていた場合、このテクニックでより多くの記憶を取ってしまい、前者の描画能力が悪化する可能性があります。しかし、であるかどうかはわかりません。なぜなら、ココアが舞台裏で何をしているのかわからないからです。誰でも説明できますか?

答えて

1

「キャッシュされた」唯一のものは、drawRect:メッセージの結果です。無効にされるまでキャッシュされます。この場合、メッセージは再び呼び出されます。

CocoaとCocoa-Touchは、メソッドで使用するオブジェクトをキャッシュしません。 2番目の例のように、自分でキャッシュすることができます。しかし、私はこのような最適化をInstrumentsなどのプロファイラを使ってテストすることを推奨します。多くのメリットがないようにコードを複雑にしないようにすることをお勧めします。

+0

無効になるのはいつですか? – Michael

+0

+1無効にすると、多くのことが無効になり、ビューの一部だけを無効にすることができます(-drawRect:CGRectを渡して無効になった部分を伝えます)。あなたが-setNeedsDisplayを呼び出すと、それはもちろん無効になります。ビューが画面に表示されたら。ビューの「状態」が変化するとき(例えば、強調表示)。ビューのサイズが変更されたとき。時にはスクロール中に(ビットマップキャッシュの最適化がいくつかありますが)。 –

+0

さらなる解説では、もしあなたがそれを手伝ってくれれば、あなた自身でグラデーションを描画することを勧めます。 iPhoneは必ずしも速いとは限りません。アップルの推奨は画像を使用することです。勾配は、多くの場合、単一ピクセル幅の画像で処理され、所望の領域を満たすように水平に引き伸ばされる。 –

0

各UIViewには独自のオフスクリーン描画バッファ可視性を取り巻くUIViewや変更によってUIViewが再描画されることはありません。すでに述べたように、再描画をトリガする特定のインスタンスがありますが、それらを発生させない限り、drawRectルーチンは呼び出されません。 (実験として、呼び出されたときにNSLog呼び出しでdrawRectルーチンを起動してみてください)描画が実際に行われる回数を制限することで、描画を「高速」に近づけることができます。

また、Sharkのようなパフォーマンス測定ツールを使用して、描画ルーチンがどれぐらいの時間を費やしているのか、その中で最も時間がかかるものを確認することができます。この分析は、実際にそうでない場合には高価かもしれないと考えるものをキャッシュしないようにするのに便利です。

関連する問題