NSRunLoop 因 NSTimer 和任何输入而冻结
由于某种原因,当我按下(单击并按住)任何控件时,我的应用程序中的 NSTimer 会冻结并且不会触发,直到我释放鼠标按钮。当我按下鼠标时它根本不会触发。这在短时间内没问题,但如果我打开弹出菜单或下拉组合框,它也会冻结。
我不确定是否有什么我错过的事情,但这似乎是不正确的行为。
我希望能够单击 NSPopUpButtonCell 的向下箭头(甚至单击并按住 NSTableView),而不会使整个 NSTimer 冻结(这会重绘 NSView)。
任何意见/建议将不胜感激。
NSTimer 以 NSDefaultRunLoopMode 模式添加到 currentRunLoop 中。
For some reason when I push down (click and hold) on any control, the NSTimer in my App freezes and does not fire until I release the mouse button. It simply does not fire while I have the mouse pressed. This is fine for short periods, but it also freezes if I have a popup menu open, or a combobox dropped down.
I'm not sure if there is something I missed, but it seems like this is incorrect behavior.
I want to be able to click the down arrow of an NSPopUpButtonCell (or even click and hold an NSTableView) without the entire NSTimer freezing (which redraws an NSView).
Any comments / suggestions would be appreciated.
The NSTimer is added to the currentRunLoop with mode NSDefaultRunLoopMode.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当鼠标按下时,运行循环位于
NSEventTrackingRunLoopMode
。因此,在运行循环返回到适当的模式之前,EventTracking 事件队列未接收到的任何事件都不会得到服务。解决这个问题的方法是将计时器添加到两种模式(默认和事件跟踪)的运行循环中。
While the mouse is down, the run loop is in the
NSEventTrackingRunLoopMode
. Therefore, any event that's not received onto the EventTracking event queue won't be serviced until the runloop returns to the appropriate mode.The way around this is to add the timer to the runloop for both modes (default and event tracking).
无需将两个或多个计时器添加到不同的运行循环或使用多线程(因为您将无法从另一个线程更新 UI),只需将计时器添加到 NSRunLoopCommonModes 即可:
Instead of adding two or more timers to different runloops or using multithreading (as you won't then be able to update the UI from another thread) simply add the timer to the NSRunLoopCommonModes:
假设您只处理应用程序中的一个线程,那么您所描述的内容是完全符合预期的。默认情况下,
NSTimer
会添加到当前的NSRunLoop
中,在您的情况下,它还负责处理 UI 交互。当它与处理 UI 交互相关时,它无法检查您的计时器并“触发”它。一个解决方案是使用多线程以避免这种束缚。这是关于这个主题的一篇很好的博客文章:http://blog.narent.com/?p=21
编辑:请参阅 Dave 的帖子,了解替代(且更优雅的 IMO)解决方案
另请参阅:
Assuming you're just dealing with one thread in your application, what you described is perfectly expected. By default,
NSTimer
's are added to the currentNSRunLoop
which, in your case, is also responsible for dealing with UI interaction. When it gets tied up with handling UI interaction, it can't check your timer and "fire" it.A solution is to use multi-threading so as to avoid this tie-up. Here's a nice blog post on this very subject: http://blog.narent.com/?p=21
EDIT: See Dave's post for an alternative (and more elegant IMO) solution
Also see: