Objective c 如何允许用户在不暂停应用程序更新循环的情况下调整NSSlider?
注意:以下更新… 我有一个cocoa桌面应用程序,它由一系列围绕自定义NSView的控件组成。我正在使用displayLink驱动更新 当用户单击NSControl(滑块、按钮、复选框、单选按钮)时,应用程序似乎会冻结,直到释放鼠标。事实上,我可以确认displayLink回调(getFrameForTime)在此期间没有触发。如果我创建了一个计时器,它也不会启动,这两个计时器都将保持暂停状态,直到用户释放鼠标,此时应用程序将继续更新 控件已绑定,如果我从另一个线程更新该值(例如,通过MIDI接口的回调),滑块的行为将与预期的一样:它移动,值更新,应用程序不会暂停 我觉得这应该是一个相当明显的解决办法,但我被难住了Objective c 如何允许用户在不暂停应用程序更新循环的情况下调整NSSlider?,objective-c,multithreading,macos,cocoa,Objective C,Multithreading,Macos,Cocoa,注意:以下更新… 我有一个cocoa桌面应用程序,它由一系列围绕自定义NSView的控件组成。我正在使用displayLink驱动更新 当用户单击NSControl(滑块、按钮、复选框、单选按钮)时,应用程序似乎会冻结,直到释放鼠标。事实上,我可以确认displayLink回调(getFrameForTime)在此期间没有触发。如果我创建了一个计时器,它也不会启动,这两个计时器都将保持暂停状态,直到用户释放鼠标,此时应用程序将继续更新 控件已绑定,如果我从另一个线程更新该值(例如,通过MIDI接
- 在IB中选中“continuous”会像广告中所说的那样:连续发送值,但在释放鼠标之前仍会显示此行为(阻止UI更新)
- 这似乎与NSControl上的mouseDown有关?为什么会出现这种情况,我真的需要对所有UI元素进行子类化来改变这种行为(似乎很极端)
- DisplayLink位于自己的线程中,那么为什么主线程上的鼠标向下移动会阻止它呢?如果是这种情况,鉴于禁止从主线程以外的其他线程更新Cocoa UI,我该如何处理它
为什么CVDisplayLink会阻止NSEventTrackingRunLoopMode?单击NSControl时,只要鼠标按下,运行循环模式就会从
NSDefaultRunLoopMode
变为NSEventTrackingRunLoopMode
。这意味着只有已添加到此模式的运行循环源(显示链接)和计时器才会触发
您可以使用-[NSRunLoop addTimer:forMode:][/code>将计时器添加到任何模式。对于显示链接,等效的方法是-[CADisplayLink addToRunLoop:forMode:][/code>
要使动画在事件跟踪期间继续,请执行以下操作:
[myDisplayLink addToRunLoop:[NSRunLoop currentRunLoop]
forMode:NSEventTrackingRunLoopMode];
测试项目显示您正在从显示链接的回调调用视图的display
方法
当注释显示
消息时,即使移动滑块,也会连续调用显示链接
所以出错的是,当runloop进入事件跟踪模式时,在显示链接的线程上调用display
,直到松开鼠标,run loop返回默认模式。您可以通过在调用之前放置一个log语句,在调用之后放置一个log语句来轻松确认这一点
我不清楚为什么会发生这种情况。很明显,从后台线程调用视图的方法是非法的。您必须通过在主线程上调度setNeedsDisplay:
来触发视图的显示:
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
dispatch_async(dispatch_get_main_queue(), ^{
[(__bridge MyCustomView*)displayLinkContext setNeedsDisplay:YES];
});
return kCVReturnSuccess;
}
谢谢你给我指出了一个好的方向。。。这似乎描述了这个问题(并在很大程度上帮助我理解发生了什么),但我使用的是OSX而不是iOs,所以我使用的是CVDisplayLink而不是CADisplayLink。CVDisplayLink似乎没有提供指定runloop的方法。我会继续挖的。@andrew哦,我明白了。自从我在Mac OS上使用它已经有好几年了,我的印象是,从那以后,苹果增加了一种使用显示链接的可可方式。使用niceCADisplayLink
,在iOS上更容易操作。如果我没记错的话,CVDisplayLink
使用了自己的线程进行回调。我不明白为什么运行循环会影响这一点。抱歉。我可以确认这确实解决了NSTimer的问题,因此我相信您已诊断出问题,我只是挂断了如何访问MacOS上的displayLink timer对象(现在翻阅文档,但是的,它似乎没有CADisplayLink那么直接……它应该使用自己的线程。hrm。也许我会把所有东西都移植到iphone;)你能发布一个展示所描述行为的简单示例项目吗?当然,现在把它们放在一起……好的,项目就在这里。请注意,它确实非常小,不显示任何内容(从timer和displayLink查看控制台中的NSLog),还请注意,滑块未连接任何内容,也未执行任何操作:非常感谢!1.奇怪的但是2.老实说,我不记得为什么我在那里调用display(我的代码从苹果样板开始,在我工作时有点变化),我不需要它。非常感谢你的帮助,这让我恼火了好几年。非常欢迎你。这是真正有帮助的案例之一。有时候橡皮鸭就是这样。我刚点了一只鸭子。:D是的。。。显然,从这段代码开始太长时间没有帮助。