2011 年の WWDC ビデオ セッション 121 では、UI のパフォーマンスを向上させるために、プレゼンターはレイヤーに角の半径を直接設定するのではなく、drawRect: で UIBezierPath を使用して角を丸くすることを選択しました。
UIBezierPath を使用した描画が必然的に高速になるのはなぜですか? drawRect: 遅いソフトウェアでも発生します。
2011 年の WWDC ビデオ セッション 121 では、UI のパフォーマンスを向上させるために、プレゼンターはレイヤーに角の半径を直接設定するのではなく、drawRect: で UIBezierPath を使用して角を丸くすることを選択しました。
UIBezierPath を使用した描画が必然的に高速になるのはなぜですか? drawRect: 遅いソフトウェアでも発生します。
簡単な答え: パフォーマンスの問題が発生するまでは、おそらく CALayer の cornerRadius をそのまま使用してください。
長い答え:
まず、「描画」と「合成」を区別する必要があります。
iOS での描画は、テクスチャをピクセルで塗りつぶすという単純な作業です (CPU が制限されたタスク)。合成は、これらすべてのテクスチャを 1 つのフレームにフラット化して画面に出力する作業です (GPU 限定のタスク)。一般的に言えば、スクロールまたはアニメーション化するときは、ほとんど GPU に負担をかけます。これは、すべてのピクセルを 1 つ下にシフトするなどの理由で、GPU が朝食に食べるものです。
-drawRect: 純粋な描画で、CPU を使用してテクスチャを塗りつぶします。CALayer の cornerRadius は合成ステップで行われ、GPU に負荷をかけます。
-drawRect を使用すると、初期コストが非常に高くなり (簡単に 1 フレームよりも長くかかる可能性があります)、メモリの使用量が少なくなりますが、その後は非常にスムーズにスクロールします (他のテクスチャと同様に単なるテクスチャになります)。CALayer のコーナー半径を使用すると、コーナー半径のあるビューを大量に作成するのはとてつもなく高速ですが、12 個以上のビューを取得すると、スクロール速度に別れを告げることができます (GPU は通常のスクロール作業を行うだけでなく、ビューにコーナー半径を追加し続けます)。
しかし、私の言葉を鵜呑みにしないでください。Florian Kugler のベンチマークを採用し、iOS 6.1.3 を実行する iPhone 4S で実行しました。最初に 1/60 秒で作成できるビューの数を測定し、次にフレーム レートが 60 fps を下回る前にアニメーション化できるビューの数を測定します。つまり、初期費用とフレームレートの費用です。
| | -drawRect: | CALayer のコーナーRadus 16.6 ミリ秒でレンダリングされるビューの最大数 | 5 ビュー | 110 ビュー 60fps でアニメーション化するビューの最大数 | ~400 ビュー | 12 ビュー
(500 -drawRect: ビューでメモリを使いすぎたためにアプリが強制終了されることに注意してください)
結局のところ、私自身のプロジェクトでは、可能な限り CALayer の cornerRadius に固執する傾向があります。丸い角と -drawRect を備えた 2 つ以上のビューが必要になることはめったにありません。初期のパフォーマンス ヒットが多すぎるだけです。そして、角を丸くするためだけにビューをサブクラス化するのは、まあまあです。
ただし、最終的にどの方法を選択する場合でも、アプリのスムーズさと応答性を測定して注意を払い、それに応じて対応するようにしてください。