1

並行プログラミングとsetNeedsDisplayの呼び出しに関して、物事がどのように機能するかを理解しようとしています。私は基本的に3つのオブジェクトを持っています。

Main View - container with different UIView objects, the main one being a UIScrollView
Small Map View - a small UIView that draws a miniature version of one of the other UIView items on screem
Processor - a delegate of the Main View that calculates what's on screen and calls the Main View back with what's in view.  

したがって、何が起こっているかの簡単なユースケースは、ユーザーが ScrollView に触れてから、プロセッサが scrollView の表示内容を更新することです (座標、中心点などの計算など)。ブロックを使用してこれを行い、非同期で行います。これにより、通知が MainView オブジェクトにポストされます。

MainView が通知を受け取ると、呼び出すだけです。

[smallMap setNeedsDisplay];  // example 1

この呼び出しにいくつかのログを記録しましたが、すぐに呼び出されることがわかりました。ただし、この関数の drawRect: はすぐには呼び出されません。約2秒後に呼び出されます。

setNeedsDisplay実行ループの次のイベントで再描画が発生するようにビューをマークするだけの ことを読んだことを覚えています。

しかし、代わりにこのコードを追加すると:

// example 2
dispatch_async(dispatch_get_main_queue(), ^{
    [smallMap setNeedsDisplay];        
    });

私のビューはすぐに再描画されます。

メインイベントループで setNeedsDisplay を呼び出してすぐに何かを再描画するように要求する必要がある理由について、私は混乱していると思います。例 1 のように、私が setNeedsDisplay を呼び出すと、それはバックグラウンドまたは何かで行われ、それがすぐに再描画されない理由ですか? 舞台裏で何が起こっているかの違いを理解しようとしているので、将来何を探すべきかがわかります。例 2 のブロックのように、すぐに再描画する必要がある呼び出しをすべて持つ必要がありますか? それとも、データを非同期で処理しているため、メイン キューを要求する必要があるのでしょうか? ありがとう!

4

2 に答える 2

2

私の推測では、次の 2 つのうちの 1 つです。

別のスレッドで実行されているコードは、メイン スレッドでコードを呼び出す performSelectorOnMainThread または GCD 呼び出しを使用する代わりに、別のスレッドから MainView メソッドを呼び出しています。したがって、 setNeedsDisplay への呼び出しは、実際にはバックグラウンド スレッドで行われています。これは、他のポスターが言ったように、ノーノーです。

2 つ目の可能性は、MainView コードがメイン スレッドで実行されているが、時間のかかる処理を行ったり、別のスレッドへの同期呼び出しが終了するのを待ったりしてビジー状態になり、イベント ループを処理していないことです。

setNeedsDisplay への呼び出しにブレークポイントを設定し、デバッガーで呼び出しトレースを調べて、どのスレッドから実行されているかを確認することで、最初の可能性を除外できます。

2 番目の可能性を理解するには、もう少し作業が必要です。楽器を掘り下げる必要があるかもしれません。

于 2012-06-04T23:51:18.583 に答える
2

setNeedsDisplayは UIKIT API 呼び出しであり、UI スレッドとも呼ばれるアプリケーションのメイン スレッドから呼び出す必要があります。そのため、バックグラウンド スレッドで呼び出してもすぐには効果がなく、メイン キューでスケジュールするとすぐに効果があります。

詳細な回答については、この関連する質問https://stackoverflow.com/a/6988115/172690を参照してください。

于 2012-06-04T21:12:46.700 に答える