2

なぜ をサブクラス化し、呼び出されるメソッドUIViewを実装するのかと最初は疑問に思いましdrawRectたが、同時に、このビューにボタンやラベルを追加し、それらの位置座標を調整すると、それらも再描画されます.. . したがって、このビューの描画には 2 つのメカニズムがあるようです。1 つはそれ自体のため、もう 1 つはこのビュー内のオブジェクトのためです。

しかし、1/60 秒ごとにツリー全体がトラバースされているようです。トップ ビュー オブジェクトから開始して、iOS はすべての子を訪問し、次に を呼び出します。また、孫が訪問さdrawRectれるselfのと同じ方法で子も訪問され、次のようにdrawRect、それらの第 1 レベルの子ごとに呼び出されます。

-(void) processViewObject:(UIView *) obj {
    // pseudo code:
    foreach children "c" already sorted by zOrder from most negative to -1
        processViewObject(c)    // recursion

    if ([self needsUpdateOrNot] == YES)
        [self drawRect]

    foreach children "c" already sorted by zOrder from 1 to the greatest number
        processViewObject(c)   // recursion
}

呼び出しは 1/60 秒ごとに行われます。

processViewObject(topViewObject);    //  start from the topmost view object

任意のビューがdrawRectおよびビューの子で自分自身を描画できるように、それらの位置座標のいずれかが変更された場合、またはそれらのコンテンツが変更された場合、ダーティ ビットneedsUpdateOrNotが以前に設定されているため、自分drawRect自身を再描画するために呼び出されます。

または、実際には、ビューのダーティ ビットが設定されている場合、次のように、おそらくこのビットが再帰で子に渡されます。

    foreach children "c" already sorted by zOrder from 1 to the greatest number
        processViewObject(c, [self needsUpdateOrNot])

親のダーティ ビットが設定されている場合、このビュー内の画像全体を正しく描画するには、子も再描画する必要があります。

また、見栄えの良いボタンやラベルのそれぞれは、ボタン、チェックボックス、ラベル、その他のウィジェットなど、見栄えの良い画像を描画できる が既に実装されている単なるUIViewオブジェクトです。drawRect

これが、すべてが画面上に描画される全体的なメカニズムですか? 「自分自身を呼ばないで、呼ばせて」と聞くがdrawRect、その理由はよく分からないが、上記が全体の仕組みだとすると、それが理由のようだ。

これは実際には Microsoft Windows や他の GUI オペレーティング システムとほぼ同じメカニズムなのだろうか、いくつかのゲーム フレームワークでは、ダーティ ビットが設定されているかどうかに関係なく、すべてが描画されると思います。ゲームでは常に動きますが、フレームワークはとにかく 1/60 秒ごとにそれらすべてを描画します。

上記のzOrder処理順序は、いくつかのフレームワークのコードにあったため、すべての負の zOrder 子が最初に描画され、次にself描画され、次にすべての正の zOrder 子が描画されます。(これは、画面上にオブジェクトをペイントするペインター モデルの方法で zOrder が達成される方法です。後者の描画は、前に描画されたものを覆い隠します。)子に対する ifselfの zOrder も0同様です -- 問題の zOrder 数selfifそれは自分の兄弟に対して相対的であり、その子供に対してではありません。

上記は正確ですか?回答を提供する場合、可能であれば、ソース コードまたは参照の一部を引用して、それがどのように機能するかの標準または公式の方法であることを確認できますか?

4

3 に答える 3

6

合成と描画を混同していると思います。この 2 つは別個の概念であり、異なるポイントで作用します。

iOS では、各 UIView は、四角形の OpenGL ES テクスチャの実質的な軽量ラッパーである CALayer によって支えられています。UIView を完全に再描画する必要がある場合 (初めて表示されるとき、またはさまざまな状況で再描画が強制されたとき)-drawRect:がトリガーされ、Core Graphics を使用してベクター グラフィックスがビットマップにレンダリングされます。そのビットマップは、CALayer を介して GPU にアップロードされ、そこに保存されます。

ビューを移動したり、単純な変換 (回転、スケーリングなど) を適用したりする必要がある場合、ビューは再描画されず、バッキング レイヤーが移動されるだけで、表示されているシーンのレイヤーが合成されます。ここでも、各ビューとサブビューには独自のバッキング レイヤーがあるため、これらはビュー (レイヤー) 階層の Z オーダーで合成されます。GPU での合成は信じられないほど高速な操作であり、ビューの最初の描画よりもはるかに高速です。これにより、iOS でスムーズなスクロールやアニメーションが可能になります。これは、これらの基本的な長方形の画像が GPU 上で移動され、合成されるためです。また、ビューやレイヤーに透過性があると、スクロールなどの操作が遅くなる理由もあります。これは、不透明でないレイヤーの合成が不透明なレイヤーよりも大幅に遅いためです。

サブビューまたはそれらの上に配置された他のビューを移動しても、ビューのオーバーラップ部分は再描画されません。実際の-drawRect:再描画が発生するのは、 を使用-setNeedsDisplayして再レンダリングを強制する場合、needsDisplayOnBoundsChangeまたはサイズや形状の変化に応じて自身を再描画するように CALayer を設定する場合のみです。

jturton がリンクしているドキュメントの一部は、iOS や Mac のレイヤーに裏打ちされたビューに関しては間違っていると思います。これは、Mac にコア アニメーションがなかったときに書かれたようで、レイヤーでサポートされていない NSView がレンダリングされる方法であるため、古いリファレンスからコピー アンド ペーストされた可能性があります。これは、部分的に隠されている場合に再描画されない、レイヤーに基づくビューには当てはまりません。-drawRect:これは、レイヤーでサポートされた UIView 内で呼び出されたときにログを記録することで自分でテストできます。ビューが単に重なり合っているだけではトリガーされないことがわかります。

于 2012-05-18T17:44:57.797 に答える
2

ビューは下 (z 方向) から上に描画されます。不透明なビューなどにはさまざまな最適化があります。汚れているとマークされたすべてのビューは、実行ループの最後に再描画されます - ご想像のとおり、1/60 秒ごとのメカニズムはありません。

参考:https ://developer.apple.com/library/ios/documentation/general/conceptual/Devpedia-CocoaApp/DrawingModel.html

于 2012-05-18T05:54:32.137 に答える
1

jrturtonが参照するドキュメントから

iOS および Mac OS X での描画は、2 つのテクノロジ パスのいずれかに従い、ビューがオンデマンドで外観を更新するモデルに基づいています。

ビューの定期的な更新については、これで解決すると思います。ビューはオンデマンドでのみ更新されます。これは、処理能力が高いにもかかわらず iPhone がまだ組み込みデバイスであることを考えると理解できます。プロセッサ/メモリの動作が少ないほど良い..バッテリー寿命も考慮する必要があります..

ビューが更新される場合のいくつかのケース (再びドキュメントから)

  • ユーザーが、別のビューを部分的に隠していたビューを移動または削除します。
  • ユーザーは、含まれているスクロール ビューからビューをスクロールし、スクロールして元に戻します。
  • コードは、hidden プロパティを NO に設定することで、以前に非表示にしたビューを再び表示できるようにします。
  • コードでビューを明示的に無効にする ビューを無効にして再描画のマークを付けるには、ビューで setNeedsDisplay や
    ​​ setNeedsDisplayInRect: などのメソッドを呼び出します。

メイン イベント ループのサイクルの最後に、ウィンドウはそのビュー階層を下に進み、drawRect: メソッドを呼び出してこれらのビューに自分自身を描画するように要求します。

そのため、メイン イベント ループでは、window (これは親である) はツリー階層全体をトラバースしますが、更新が必要な子のみを更新します。他のビューはそのまま保持されます。

于 2012-05-18T06:19:07.413 に答える