Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何允许用户在不暂停应用程序更新循环的情况下调整NSSlider?_Objective C_Multithreading_Macos_Cocoa - Fatal编程技术网

Objective c 如何允许用户在不暂停应用程序更新循环的情况下调整NSSlider?

Objective c 如何允许用户在不暂停应用程序更新循环的情况下调整NSSlider?,objective-c,multithreading,macos,cocoa,Objective C,Multithreading,Macos,Cocoa,注意:以下更新… 我有一个cocoa桌面应用程序,它由一系列围绕自定义NSView的控件组成。我正在使用displayLink驱动更新 当用户单击NSControl(滑块、按钮、复选框、单选按钮)时,应用程序似乎会冻结,直到释放鼠标。事实上,我可以确认displayLink回调(getFrameForTime)在此期间没有触发。如果我创建了一个计时器,它也不会启动,这两个计时器都将保持暂停状态,直到用户释放鼠标,此时应用程序将继续更新 控件已绑定,如果我从另一个线程更新该值(例如,通过MIDI接

注意:以下更新…

我有一个cocoa桌面应用程序,它由一系列围绕自定义NSView的控件组成。我正在使用displayLink驱动更新

当用户单击NSControl(滑块、按钮、复选框、单选按钮)时,应用程序似乎会冻结,直到释放鼠标。事实上,我可以确认displayLink回调(getFrameForTime)在此期间没有触发。如果我创建了一个计时器,它也不会启动,这两个计时器都将保持暂停状态,直到用户释放鼠标,此时应用程序将继续更新

控件已绑定,如果我从另一个线程更新该值(例如,通过MIDI接口的回调),滑块的行为将与预期的一样:它移动,值更新,应用程序不会暂停

我觉得这应该是一个相当明显的解决办法,但我被难住了

  • 在IB中选中“continuous”会像广告中所说的那样:连续发送值,但在释放鼠标之前仍会显示此行为(阻止UI更新)

  • 这似乎与NSControl上的mouseDown有关?为什么会出现这种情况,我真的需要对所有UI元素进行子类化来改变这种行为(似乎很极端)

  • DisplayLink位于自己的线程中,那么为什么主线程上的鼠标向下移动会阻止它呢?如果是这种情况,鉴于禁止从主线程以外的其他线程更新Cocoa UI,我该如何处理它

非常感谢您的帮助

更新 根据@Nikolai下面的评论,我可以确认使用NSTimer并将其添加到NSEventTrackingRunLoopMode不会阻塞。然而,我真的很想使用CVDisplayLink,它(根据文档)在自己的线程中运行,不应该以这种方式被阻止。与CADisplayLink不同,我找不到一种方法来显式地将runloop分配给CVDisplayLink(似乎不是这样),因此新的问题可能是:


为什么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上使用它已经有好几年了,我的印象是,从那以后,苹果增加了一种使用显示链接的可可方式。使用nice
CADisplayLink
,在iOS上更容易操作。如果我没记错的话,
CVDisplayLink
使用了自己的线程进行回调。我不明白为什么运行循环会影响这一点。抱歉。我可以确认这确实解决了NSTimer的问题,因此我相信您已诊断出问题,我只是挂断了如何访问MacOS上的displayLink timer对象(现在翻阅文档,但是的,它似乎没有CADisplayLink那么直接……它应该使用自己的线程。hrm。也许我会把所有东西都移植到iphone;)你能发布一个展示所描述行为的简单示例项目吗?当然,现在把它们放在一起……好的,项目就在这里。请注意,它确实非常小,不显示任何内容(从timer和displayLink查看控制台中的NSLog),还请注意,滑块未连接任何内容,也未执行任何操作:非常感谢!1.奇怪的但是2.老实说,我不记得为什么我在那里调用display(我的代码从苹果样板开始,在我工作时有点变化),我不需要它。非常感谢你的帮助,这让我恼火了好几年。非常欢迎你。这是真正有帮助的案例之一。有时候橡皮鸭就是这样。我刚点了一只鸭子。:D是的。。。显然,从这段代码开始太长时间没有帮助。