1. ホーム
  2. iphone

[解決済み] drawRectを使うか使わないか(drawRect/Core Graphicsとsubview/imagesをいつ使うか、なぜ使うか)?

2022-05-17 02:35:18

質問

この質問の目的を明確にするために。私は、サブビューとdrawRectの両方を使用して複雑なビューを作成する方法を知っています。私は、いつ、なぜ、一方を他方よりも使用するのかを完全に理解しようとしています。

私はまた、前もってそれほど最適化する意味がないこと、そしてプロファイリングを行う前に、より困難な方法で何かを行うことを理解しています。私は両方の方法に慣れていて、より深い理解を求めているのだと考えています。

私の混乱の多くは、テーブル ビューのスクロール パフォーマンスを本当にスムーズかつ高速にする方法を学ぶことから来ています。もちろん、このメソッドのオリジナル ソースは の作者で、Twitter の背後にある for iPhone (旧 tweetie) の作者です。 基本的には、テーブルのスクロールを滑らかにするために、サブビューを使用せず、代わりに1つのカスタムuiviewですべての描画を行うことが秘密であると書かれています。 基本的に、多くのサブビューを使用すると、多くのオーバーヘッドを持ち、親ビュー上で常に再合成されるため、レンダリングが遅くなるようです。

公平を期すために、これは 3GS がかなり真新しいときに書かれたもので、iDevice はそれ以来ずっと速くなっています。それでも このメソッド 定期的に 推奨 にて インターウェブ などで、高性能なテーブルのために使われています。実際、この方法は Apple のテーブルのサンプルコード で提案されており、いくつかの WWDC ビデオでも提案されています ( iOS 開発者のための実用的なドローイング )、そして多くの iOS プログラミングの本 .

さらに すごいツール を使用して、グラフィックをデザインし、そのための Core Graphics コードを生成することもできます。

最初は、Core Graphics の存在には理由があるのだろうと思いました。それは FAST です。

Core Graphics

しかし、「可能な場合は Core Graphics を使用する」という考えを理解したとたん、drawRect がしばしばアプリの応答性の悪さの原因となり、メモリの面で非常に高価で、CPU に本当に負担をかけていることがわかり始めました。基本的には、次のようなことです。 drawRect のオーバーライドを避ける ということです(WWDC 2012 iOSアプリのパフォーマンス。グラフィックスとアニメーション )

だから、私は、すべてのように、それは複雑だと思います。もしかしたら、私や他の人が drawRect を使用する際の When's and Why's を理解する手助けができるかもしれませんね。

Core Graphics を使用するいくつかの明白な状況を見ました。

  1. 動的なデータを持っている (Apple の株価チャートの例)
  2. 単純なリサイズ可能な画像では実行できない柔軟な UI 要素がある場合。
  3. 動的なグラフィックを作成しており、一度レンダリングすると複数の場所で使用される場合。

Core Graphics を避けるべき状況があるようですね。

  1. ビューのプロパティを個別にアニメートする必要がある。
  2. ビューの階層が比較的小さいため、CGを使用することで余分な労力がかかると感じたら、それは利益に見合わない
  3. 全体を再描画することなく、ビューの一部を更新したい。
  4. 親ビューのサイズが変更されたときにサブビューのレイアウトを更新する必要がある

だから、あなたの知識を授けてください。どのような状況で drawRect/Core Graphics (これはサブビューでも達成可能) に手を伸ばしますか? どのような要因でその決定を下すのでしょうか? テーブルセルのスクロールを滑らかにするために、1つのカスタムビューで描画することが推奨されているのに、Appleは一般的なパフォーマンス上の理由からdrawRectを推奨しているのはなぜですか?シンプルな背景画像についてはどうですか (サイズ変更可能な png 画像を使用する場合と CG で作成する場合)?

この主題の深い理解は、価値のあるアプリを作るために必要ではないかもしれませんが、私は理由を説明することができないまま、技術の間で選択することが好きではありません。私の脳は私に怒ります。

質問の更新

皆さん、情報をありがとうございます。ここにいくつかの明確な質問があります。

  1. コア グラフィックスで何かを描いているが、UIImageViews とプリレンダリングされた png で同じことを達成できる場合、常にそのルートに行くべきですか。
  2. 似たような質問です。特に のようなバッドアスツールでは のような、特に、インターフェイスの要素をコアグラフィックスで描画することを考慮すべき時はいつですか?(例えば、20種類のカラーバリエーションを持つボタンなどです。他のケースは?)
  3. 私の以下の回答での理解を考慮すると、テーブルセルのための同じパフォーマンス利得は、おそらく、複雑なUIViewのレンダリング自体の後にセルのスナップショットビットマップを効果的にキャプチャして、複雑なビューをスクロールして隠している間にそれを表示することによって得られるでしょうか。もちろん、いくつかの問題は解決されなければなりません。ただ、私が持っていた興味深い考えです。

どのように解決するのですか?

できる限り UIKit とサブビューにこだわってください。より生産的になり、メンテナンスが簡単になるはずのすべての OO メカニズムを活用することができます。UIKit から必要なパフォーマンスを得られない場合、または UIKit で一緒に描画効果をハックしようとするとより複雑になることがわかっている場合は、Core Graphics を使用します。

一般的なワークフローは、サブビューを持つテーブルビューを構築することです。アプリがサポートする最も古いハードウェアでフレーム レートを測定するために、Instruments を使用します。60fps が得られない場合は、CoreGraphics にドロップダウンします。これをしばらく続けていると、UIKit がおそらく時間の無駄である場合の感覚がわかってきます。

では、なぜCoreGraphicsは速いのでしょうか?

CoreGraphicsは本当は速くないんです。常に使用されているのであれば、おそらく遅いと思われます。これはリッチな描画 API で、GPU にオフロードされる多くの UIKit の作業とは対照的に、その作業は CPU で実行される必要があります。画面上を移動するボールをアニメーション化する必要がある場合、1秒間に60回もビューのsetNeedsDisplayを呼び出すのはひどい考えです。ですから、個別にアニメーションさせる必要のあるビューのサブコンポーネントがある場合、各コンポーネントは別々のレイヤーにする必要があります。

もう一つの問題は、drawRectでカスタム描画を行わない場合、UIKitはdrawRectが不要になるようにストックビューを最適化したり、合成でショートカットをしたりすることがあります。drawRectをオーバーライドすると、UIKitはあなたが何をしているのかわからないので、ゆっくりとした道を歩まなければなりません。

これら2つの問題は、テーブルビューのセルの場合、利点に勝ることがあります。ビューが最初に画面に表示されたときに drawRect が呼び出された後、コンテンツはキャッシュされ、スクロールは GPU によって実行される単純な変換になります。複雑な階層構造ではなく、単一のビューを扱っているため、UIKitのdrawRectの最適化はあまり重要ではなくなります。つまり、Core Graphicsの描画をどれだけ最適化できるかがボトルネックになるわけです。

できる限り、UIKitを使う。動作する最も単純な実装を行いましょう。プロファイル。インセンティブがあるときは、最適化する。