記事ディレクトリ
オフスクリーンレンダリング
UIView と CALayer の関係
- UIView は UIResponder を継承し、 UIApplication、UIViewController、UIView、UIView から派生したすべての UIKit クラスなど、システムによって渡されるイベントを処理できます。各 UIView 内には CALayer があり、コンテンツの描画と表示を提供し、内部 RootLayer のプロキシ ビューとして機能します。
- CALayer は NSObject クラスを継承し、UIView によって提供されるコンテンツを表示します。CALayer には、背景色、コンテンツ、境界線という 3 つの視覚要素がありますが、このうちコンテンツの本質は CGImage です。
GPU 画面のレンダリングには 2 つの方法があります。
1. オンスクリーン レンダリング (現在の画面レンダリング) は、
現在表示に使用されている画面バッファ上で GPU のレンダリング操作が実行されることを意味します。
2. オフスクリーン レンダリング (オフスクリーン レンダリング) は、
GPU がレンダリング操作のために現在の画面バッファーの外側にバッファーを開くことを指します。
現在の画面レンダリングでは、新しいキャッシュを作成したり、新しいコンテキストを開く必要がないため、オフスクリーン レンダリングよりもパフォーマンスが向上します。ただし、現在の画面レンダリングの制限 (独自のコンテキストのみ、制限された画面キャッシュなど) により、場合によっては、現在の画面レンダリングをレンダリングによって解決できない場合、オフスクリーン レンダリングが使用されます。
オフスクリーン レンダリングの理由:
Apple システムはビューを一度に 1 つずつ処理できません。ビューを 1 つずつ処理する必要があります。その後、オフスクリーン バッファを開いて、処理されたビューを 1 つずつ保存する必要があります。このオフスクリーン バッファは、オフスクリーンレンダリングへ。
オフスクリーン レンダリングは非常に多くのパフォーマンスを消費しますが、なぜそのようなメカニズムがあるのでしょうか?
一部のエフェクトは画面に直接表示されないと考えられており、別の場所で追加の処理と事前合成が必要になります。レイヤー プロパティの混合物は、事前合成せずに画面上に直接描画できないため、オフスクリーン レンダリングが必要です。
オフスクリーンでレンダリングするとどうなりますか?
- レイヤーのマスクを設定します (
layer.mask
) - レイヤーの
layer.masksToBounds / view.clipsToBounds
プロパティを次のように設定します。true
- レイヤ
layer.allowsGroupOpacity
プロパティをYES
とに設定しますlayer.opacity小于1.0
layer.shadow *
レイヤーに影( )を設定します。- レイヤーをラスタライズする
layer.shouldRasterize=true
- の付いたレイヤーは
layer.cornerRadius
、もちろんすべての角が丸いわけではありませんが、オフスクリーンlayer.edgeAntialiasingMask
レンダリングが発生します。layer.allowsEdgeAntialiasing
UILabel
テキスト ( 、、CATextLayer
などを含む任意の種類Core Text
)。CGContext
描画メソッドを使用すると、drawRect :
ほとんどの場合、たとえ空の実装であっても、オフスクリーン レンダリングが行われます。
オフスクリーン レンダリングは非常に悪いのに、なぜ強制的にオンにする必要があるのでしょうか?
画像が複数のレイヤーと混合されている場合、これらのレイヤーは移動するたびにフレームごとに再合成する必要があり、パフォーマンスが非常に消費されます。ラスタライズをオンにすると、初めてビットマップ キャッシュが生成され、このキャッシュは再度使用されるときに再利用されます。ただし、レイヤーが変更されると、ビットマップ キャッシュが再生成されます。したがって、この機能は通常は使用できずUITableViewCell
、セルの多重化によりパフォーマンスが低下します。静的コンテンツのレイヤーが多数あるグラフィックスに最適です。さらに、生成されるビットマップ キャッシュのサイズは制限されており、通常は 2.5 画面サイズです。キャッシュが 100 ミリ秒以内に使用されなかった場合、キャッシュも削除されます。したがって、使用シナリオに応じて決定する必要があります。
オフスクリーンレンダリングを回避するにはどうすればよいですか?
1. 丸い角の最適化:
1: ベジェ曲線 UIBezierPath と Core Graphics フレームワークを使用して、丸い角を描画します
。 2. CAShapeLayer と UIBezierPath を使用して、丸い角を設定します。
一般に、CAShapeLayer を使用すると、消費メモリが少なくなり、レンダリングが高速になります。最適化スキーム 2 を使用することをお勧めします。
2.影
影については、レイヤーが単純な幾何学的図形や角の丸い図形の場合、shadowPath を設定することでパフォーマンスを最適化し、パフォーマンスを大幅に向上させることができます。例は次のとおりです。
mageView.layer.shadowColor=[UIColorgrayColor].CGColor;
imageView.layer.shadowOpacity=1.0;
imageView.layer.shadowRadius=2.0;
UIBezierPath *path=[UIBezierPathbezierPathWithRect:imageView.frame];
imageView.layer.shadowPath=path.CGPath;
shouldRasterize プロパティ値を YES に設定することで、オフスクリーン レンダリングを強制することもできます。実際、それはラスタライズです。