8

我有:

  • 具有自定义视图的 NSStatusItem(在辅助线程中滚动文本),辅助线程更新内部状态并使用 setNeedsDisplay 通知主线程。
  • 在 mouseDown 上,会弹出一个 NSMenu。
  • 但是,如果选择了 NSMenu 中的任何 NSMenuItem,或者如果检测到第二个 mouseDown 并且 NSMenu 消失,则滚动文本动画会断断续续。

似乎 NSMenu 默认视图在执行动画时会阻塞主线程。我已经通过让辅助线程输出 time_since_last_loop 与视图(这是主线程)的 drawRect: 来测试这一点,并且只有 drawRect 显示口吃。自定义视图的 drawRect 从 ~30 fps 下降到 5 几帧。

有什么方法可以让 NSMenu 动画非阻塞,或者与自定义视图的 drawRect 并发?

4

1 回答 1

0

我使用 NSTimer 和 NSEventTrackingRunLoopMode 来解决类似的问题。

在您的主线程中,创建一个计时器:

    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];

然后在你的更新:例程中,检查 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 回答