NSRunLoop冻结了NSTimer和任何输入

时间:2011-01-07 05:09:20

标签: objective-c cocoa nstimer nsrunloop

出于某种原因,当我按下任何控件上的(单击并按住)时,我的应用程序中的NSTimer会冻结,直到我释放鼠标按钮才会触发。我按下鼠标时根本不会触发。这对于短期来说很好,但如果我打开一个弹出菜单,或者组合框掉落,它也会冻结。

我不确定是否有遗漏的东西,但似乎这是不正确的行为。

我希望能够点击NSPopUpButtonCell的向下箭头(甚至点击并按住NSTableView),而不会冻结整个NSTimer(重绘NSView)。

任何意见/建议将不胜感激。

使用模式NSDefaultRunLoopMode将NSTimer添加到currentRunLoop。

3 个答案:

答案 0 :(得分:8)

当鼠标停止运行时,运行循环位于NSEventTrackingRunLoopMode。因此,在runloop返回到适当的模式之前,任何接收到EventTracking事件队列的事件都不会得到服务。

解决这个问题的方法是将定时器添加到两种模式的runloop(默认和事件跟踪)。

答案 1 :(得分:8)

不是将两个或多个计时器添加到不同的runloops或使用多线程(因为您无法从另一个线程更新UI),只需将计时器添加到NSRunLoopCommonModes:

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

答案 2 :(得分:0)

假设您只是处理应用程序中的一个线程,那么您所描述的内容是完全可以预期的。默认情况下,NSTimer被添加到当前NSRunLoop中,在您的情况下,它还负责处理UI交互。当它与处理UI交互相关时,它无法检查您的计时器并“触发”它。

解决方案是使用多线程以避免这种束缚。这是一篇关于这个主题的好文章:http://blog.narent.com/?p=21

编辑:请参阅Dave的帖子,了解替代方案(以及更优雅的IMO)解决方案

另见: