Jul 092012
 

Objective-CでUIViewを使う場合、drawRect:とsetNeedsDisplay等の描画に関係するメソッドがある。関係のまとめ。手始めにUIViewControllerのライフサイクル、init初期化メソッド(initializer)からloadViewへと順に考えていく。

ライフサイクルの流れ(表示まで)

  1. init(initWith)
  2. loadView
  3. viewDidLoad
  4. viewWillAppear
  5. viewDidAppear
各メソッドの詳細のまとめ記事(http://blog.f60k.com/initwithcoder_…hnibnamebundle/)

drawRect

システムにおいて、ビジュアルの画面描画は負荷の高い処理となる。再描画を最小限にすることが表示を高速化するコツとなる。

いつどのようにdrawRectは呼ばれるか?

通常、UIViewはCALayerのdelegateであり、アニメーションなど表示更新のタイミングでdelegateメソッドを呼び出し、UIViewに実装されているdelegateメソッドdrawLayer:inContext:メソッドが呼び出される。drawLayer:inContext:メソッドは、デフォルトでdrawRectを呼び出す。つまり、ユーザ定義でサブクラス内でdrawLayer:inContext:メソッドを実装していない場合、単純にdrawRectが呼ばれる。

layer階層やsubviewで分割

drawRectメソッドは最も一般的な描画メソッドで描画のカスタマイズに使われる。描画範囲を最小にするためにはlayer階層やsubviewで分割し、細かい単位で行うのが良いとされている。drawRectはViewというのが最小単位となるためview全体のredrawになるとされているためあまりよい方法ではない、一般的(大衆的)な方法ですらある。なおlayer単位で描画する場合にdrawLayer:inContext:に記述する。

全体のビュー更新を避ける

setNeedsDisplayでもsetNeedsDisplayInRectでも全体のビュー更新を行うようにマークされる。例えば、画像(UIImage)をアニメーションさせたり移動や回転などさせる場合、画像用のviewやlayerを作成して行うのが良い。これによりiOSがscreenを更新する時点で、viewのdrawRectで呼ばずに済み親ビュー全体の更新を避けることができ、つまりCGContextDrawImageや-drawInRectも呼ばずに済む。

drawRect

  • このメソッドはビューの描画を更新する。
  • UIViewを一つの要素と扱う。
  • 一つの要素の単位で再描画される。
  • 描画のキャッシュ(pixels)がされる。
  • 更新が必要な場合に呼び出される。

setNeedsDisplay/setNeedsDisplayInRect

  • drawRectを呼び出す予約をする。

display

  • 即座にdrawRectを呼び出す。

 

遅い場合

UIViewの中から、つまり[self setneedsdisplay]になっているとselfに対応したUIView全体に更新(drawrect:)が呼び出される。親ビューの上にsubviewが乗っているケースでは、subviewの背景が透過でなければ親は見えない。この重なった状態でselfとsubviewにsetneedsdisplayを送るとちらつくので注意。

  • opaqueプロパティを見直す(半透明合成は重いのはパソコン全般昔からの通説)
  • layerに細分化する(描画範囲を狭める)
  • subviewにして更新はsubviewに対してのみsetneedsdisplayする(描画範囲を狭める)

 

参考サイト https://developer.apple.com/library/ios/#qa/qa1708/_index.html#//apple_ref/doc/uid/DTS40010245 http://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW10

コメント

個のコメント

Powered by Facebook Comments

 Posted by at 04:31

Sorry, the comment form is closed at this time.