2

注:以下を更新...

カスタム NSView の一連のコントロールで構成されるココア デスクトップ アプリケーションがあります。私は更新を促進するためにdisplayLinkを使用しています。

ユーザーが NSControl (スライダー、ボタン、チェックボックス、ラジオ ボタン) をクリックすると、マウスが離されるまでアプリケーションがフリーズしたように見えます。実際に、displayLink コールバック (getFrameForTime) がその間に発生していないことを確認できます。タイマーを作成すると、それも起動しません。ユーザーがマウスを離すまで、両方とも一時停止したままになり、その時点でアプリケーションが更新を再開します。

コントロールがバインドされ、別のスレッドからその値を更新すると (たとえば、MIDI インターフェイスからのコールバックを介して)、スライダーは期待どおりに動作します。スライダーは移動し、値が更新され、アプリケーションは一時停止しません。

これはかなり明白な修正であるべきだと思いますが、困惑しています。

  • IB で「continuous」をチェックすると、宣伝どおりに動作します。値は継続的に送信されますが、マウスが離されるまでこの動作 (UI の更新を妨げる) が引き続き発生します。

  • これは、NSControl の mouseDown に特に関連しているようですか? なぜこれがブロックされるのでしょうか。また、この動作を変更するには、すべての UI 要素をサブクラス化する必要があるのでしょうか (極端なようです)。

  • DisplayLink は独自のスレッドにあるのに、メイン スレッドの mouseDown がそれをブロックするのはなぜですか? この場合、メイン スレッド以外から Cocoa UI を更新することを差し止められた場合、どのように対処すればよいでしょうか?

どんな助けでも大歓迎です。

アップデート

以下の@Nikolaiのコメントによると、NSTimerを使用してNSEventTrackingRunLoopModeに追加してもブロックされないことを確認できます。ただし、(ドキュメントによると)独自のスレッドで実行され、この方法でブロックされるべきではない CVDisplayLink を使用したいと思います。CADisplayLink とは異なり、ランループを CVDisplayLink に明示的に割り当てる方法が見つからないため (そのようには機能しないようです)、おそらく新しい質問は次のようになります。

NSEventTrackingRunLoopMode で CVDisplayLink がブロックされるのはなぜですか?

4

2 に答える 2

3

NSControl をクリックすると、マウスが押されている限り、実行ループ モードが からNSDefaultRunLoopModeに変わります。NSEventTrackingRunLoopModeつまり、このモードに追加された実行ループ ソース (表示リンク) とタイマーのみが起動します。

を使用して、任意のモードにタイマーを追加できます-[NSRunLoop addTimer:forMode:]。表示リンクの場合、同等のメソッドは-[CADisplayLink addToRunLoop:forMode:]です。

イベント トラッキング中にアニメーションを継続するには、次のようにします。

[myDisplayLink addToRunLoop:[NSRunLoop currentRunLoop]
                    forMode:NSEventTrackingRunLoopMode];
于 2013-08-29T12:10:24.817 に答える