8

私は持っている:

  • カスタム ビュー (セカンダリ スレッドでテキストをスクロールする) を持つ NSStatusItem。セカンダリ スレッドは内部状態を更新し、setNeedsDisplay でメイン スレッドに通知します。
  • mouseDown で、NSMenu がポップアップします。
  • ただし、NSMenu のいずれかの NSMenuItem が選択されている場合、または 2 回目の mouseDown が検出されて NSMenu がフェードすると、テキストのスクロール アニメーションが途切れます。

アニメーションの実行中に NSMenu のデフォルト ビューがメイン スレッドをブロックしているように見えます。ビュー (メイン スレッド) の drawRect: に対してセカンダリ スレッド出力 time_since_last_loop を使用してこれをテストしましたが、drawRect だけがスタッターを示しています。カスタム ビューの drawRect は、数フレームで ~30 fps から 5 に低下します。

NSMenu アニメーションをブロックしないようにする方法、またはカスタム ビューの drawRect と同時に行う方法はありますか?

4

1 に答える 1

0

同様の問題を解決するために、NSEventTrackingRunLoopMode で NSTimer を使用しました。

メイン スレッドで、タイマーを作成します。

    updateTimer = [[NSTimer scheduledTimerWithTimeInterval:kSecondsPerFrame target:self selector:@selector(update:) userInfo:nil repeats:YES] retain];

   // kpk important: this allows UI to draw while dragging the mouse.
   // Adding NSModalPanelRunLoopMode is too risky.
    [[NSRunLoop mainRunLoop] addTimer:updateTimer forMode:NSEventTrackingRunLoopMode];

次に update: ルーチンで、NSEventTrackingRunLoopMode を確認します。

   // only allow status updates and drawing (NO show data changes) if App is in
   // a Modal loop, such as NSEventTrackingRunLoopMode
   NSString *runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
   if ( runLoopMode == NSEventTrackingRunLoopMode )
   {
       ... do periodic update tasks that are safe to do while
       ... in this mode
       ... I *think* NSMenu is just a window
       for ( NSWindow *win in [NSApp windows] )
       {
          [win displayIfNeeded];
       }

       return;
   }

   // do all other updates
   ...
于 2017-01-06T20:23:38.787 に答える