0

多くのサブビューを含むいくつかのビューがあり、アニメーション中のパフォーマンスが非常に悪いです。

役立つ可能性がある 1 つの方法は、階層をコンテキストにレンダリングしてフラット化することです。これが機能するには、フラット化できるようにしたい各ビューを、ビューに直接ではなく、すべてのサブビューをコンテナーに追加するように構築する必要があります。また、階層の平坦化を実行する -drawRect: を実装する必要があります。

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.containerLayer renderInContext:context];
}

トリックは、このコンテナ レイヤが のサブレイヤとして追加されないことですself.layer。Core Animation の場合、階層がフラットに見えます。

しかし、このようなことを試みる前に、それを行うためのより良い方法はありますか?

私が懸念しているのは、オンデマンドでフラット化したいビューのビュー階層を保持する追加のコンテナー レイヤーを作成する必要があることです。-drawRect: -setNeedsDisplay を呼び出したときにのみ呼び出されるので、問題ないようです。

そのようなコンテナを必要とせずにビューのサブビューを平坦化する方法はありますか?

問題は、サブビューの多くが -addSubview: を呼び出すことによって追加されることです。そのためself.layer、代わりにコンテナーがなければ、それ自体以外に平坦化できる単一のレイヤーはありません。

私がこれをした場合:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.layer renderInContext:context];
}

これはあまり意味がありませんか?サブビューの階層全体がこのレイヤーにアタッチされることを意味しますが、このレイヤーはビューに関連付けられているため、ビュー階層がフラットではないため、コンテキストにレンダリングする必要はありません。

4

1 に答える 1

2

まず、 を見てください[CALayer shouldRasterize]。あなたがやろうとしていることの多くを処理するかもしれません。

第二に、「多くの」サブビューを持つことは、しばしば悪い考えです。ビューは重いオブジェクトです。それらすべてでイベント (タッチ) 処理が必要でない限り、ビューをレイヤーに変更することを検討する必要があります。場合によっては、独自のレイヤー ヒット テストを行う必要がある場合でも、価値がある場合があります (つまり、どのレイヤーがタッチされたかをビューに認識させます)。

最後に、電話をかけrenderInContext:drawRect:も利益が得られる可能性はほとんどありません。呼び出しrenderInContext:は、(a) バックグラウンド スレッドで、または (b) より少ない頻度で呼び出すことができる場合にのみ、実際にメリットがありますdrawRect:。それ以外の場合は、すべて同じ作業を行っているだけです。

于 2012-09-09T21:51:40.540 に答える