2011-01-07 14 views
1

何らかの理由で、何らかの理由でコントロール上で(クリックして)押したときに、アプリケーションのNSTimerがフリーズし、マウスボタンを離すまで起動しません。私はマウスを押している間は、単に発射しません。これは短期間では問題ありませんが、ポップアップメニューが開いている場合や、コンボボックスがドロップダウンした場合にもフリーズします。NSRunLoopがNSTimerと任意の入力でフリーズする

私が逃したものがあるかどうかはわかりませんが、これは間違った動作です。

NSPopUpButtonCellの下向き矢印をクリックする(またはNSTableViewをクリックして保持する)ことができ、NSTimer全体がフリーズすることなく(NSViewを再描画する)できます。

ご意見/ご提案をいただければ幸いです。

NSTimerは、モードNSDefaultRunLoopModeでcurrentRunLoopに追加されます。

答えて

8

マウスがダウンしている間、実行ループはNSEventTrackingRunLoopModeにあります。したがって、EventTrackingイベントキューに受信されたではないのイベントは、runloopが適切なモードに戻るまで保守されません。

これを回避する方法は、両方のモード(デフォルトとイベントトラッキング)のためにタイマーをrunloopに追加することです。

+0

それは完全に機能しました。ご協力ありがとうございました!副問として、接続(NSInputStream/NSOutputStream)はNSConnectionReplyModeにあるべきですか? – David

0

あなたがアプリケーション内の1つのスレッドを扱っているだけであれば、記述した内容は完全に期待されます。デフォルトでは、現在のNSRunLoopにはNSTimerが追加されています。あなたの場合は、UIのやりとりを担当しています。 UIのやりとりを処理する際に縛られると、タイマーをチェックして「起動」できません。

解決策は、このタイアップを回避するためにマルチスレッドを使用することです。ここでは、この非常にテーマに素敵なブログ記事です:http://blog.narent.com/?p=21

EDIT:代替のためのを参照してくださいDaveのポスト(よりエレガントIMO)ソリューション

も参照してください。

+0

確かにマルチスレッド* a *解決策ですが、それだけではありません。 –

+0

訂正してくれてありがとう、良いことを知っている。あなたの解決策はもっと良く見えます! – Sam

+0

ありがとうございます。 2番目のスレッドでタイマーを実行することは素晴らしい選択肢です。 UIの更新をトリガーするためにタイマーを使用している場合は、メインスレッド以外のUIからUIを更新することは想定されていないため、主な理由はありません。私が推測するメインスレッドにコールバックすることができます...)。 –

8

代わりの異なるrunloopsに二つ以上のタイマーを追加したり、マルチスレッドを使用して(あなたはその後、別のスレッドからUIを更新することはできませんと)単にNSRunLoopCommonModesにタイマーを追加するには:

NSTimer *myTimer = [NSTimer timerWithTimeInterval:RefreshInterval target:self selector:@selector(doWork) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSRunLoopCommonModes]; 
+0

完璧 - これは、UIスレッドがアニメーションで忙しいときに私にとって問題を解決しました –

関連する問題