5

頻繁に変更されるコンテンツと、あまり変更されないコンテンツを持つカスタム NSView オブジェクトを作成しています。結局のところ、変更頻度の低い部分ほど、描画に最も時間がかかります。私がやりたいのは、これら 2 つの部分を異なるレイヤーにレンダリングして、どちらか一方を個別に更新できるようにすることです。これにより、ユーザーのユーザー インターフェイスが遅くなるのを防ぐことができます。

どうすればこれを行うことができますか?私はこの種のことについて多くの優れたチュートリアルを見つけたことがなく、CALayer での NSBezierPaths のレンダリングについて話しているものもありません。アイデアはありますか?

4

1 に答える 1

4

あなたの推測は正しいです。これは実際に描画を最適化するための優れた方法です。要素が上に移動したときに再描画を避けたい大きな静的背景がいくつかあった場合、私は自分でそれを行いました。

CALayerビュー内のコンテンツ アイテムごとにオブジェクトを追加するだけです。レイヤーを描画するには、ビューを各レイヤーのデリゲートとして設定してから、drawLayer:inContext:メソッドを実装する必要があります。

そのメソッドでは、各レイヤーのコンテンツを描画するだけです:

- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx
{
    if(layer == yourBackgroundLayer)
    {   
        //draw your background content in the context
        //you can either use Quartz drawing directly in the CGContextRef,
        //or if you want to use the Cocoa drawing objects you can do this:
        NSGraphicsContext* drawingContext = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES];
        NSGraphicsContext* previousContext = [NSGraphicsContext currentContext];
        [NSGraphicsContext setCurrentContext:drawingContext];
        [NSGraphicsContext saveGraphicsState];
        //draw some stuff with NSBezierPath etc
        [NSGraphicsContext restoreGraphicsState];
        [NSGraphicsContext setCurrentContext:previousContext];
    }
    else if (layer == someOtherLayer)
    {
        //draw other layer
    }
    //etc etc
}

いずれかのレイヤーのコンテンツを更新したい場合は、 を呼び出すだけ[yourLayer setNeedsDisplay]です。次に、上記のデリゲート メソッドを呼び出して、レイヤーの更新されたコンテンツを提供します。

デフォルトでは、レイヤー コンテンツを変更すると、コア アニメーションは新しいコンテンツに優れたフェード トランジションを提供することに注意してください。ただし、描画を自分で処理している場合、おそらくこれは望ましくないため、レイヤーのコンテンツが変更されたときにアニメーションでデフォルトのフェードが発生するのを防ぐために、actionForLayer:forKey:デリゲート メソッドを実装し、null を返すことでアニメーションを防止する必要があります。アクション:

- (id<CAAction>)actionForLayer:(CALayer*)layer forKey:(NSString*)key 
{
    if(layer == someLayer)
    {
        //we don't want to animate new content in and out
        if([key isEqualToString:@"contents"])
        {
            return (id<CAAction>)[NSNull null];
        }
    }
    //the default action for everything else
    return nil;
}
于 2012-02-21T12:23:46.787 に答える