在我正在处理的程序中,我正在执行大量数据处理,并且希望能够绘制自定义NSView以直观地表示该过程。
使用GCD从主线程处理数据处理(使用dispatch_sync作为需要保留的顺序):
for (int i=0; i<iterations; i++) {
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Add a data crunching task to the queue!
});
}
当处理开始时,我初始化一个计时器,用于要求自定义显示器定期重绘(一旦完成所有处理任务,该计时器就会失效):
-(void)onTick:(NSTimer *)timer {
[_customView setNeedsDisplay:YES];
// Update some other UI object (labels etc.)
}
我按预期工作了,但是我现在注意到的唯一问题是,如果我执行某项操作,例如单击并按住同一窗口上的按钮,或者在进程进行时开始拖动滑块,则重绘直到我放开鼠标才会阻止自定义视图!
有什么方法可以防止这种情况发生,最好不要将所有控件移到单独的窗口上!
答案 0 :(得分:3)
yip计时器在runloop上,而在拖放/跟踪模式下,它不会被解雇,因为runloop不是普通模式的高级
将其添加到所需的模式中:
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(myTimerAction:) userInfo:nil repeats:YES];
[runloop addTimer:timer forMode:NSRunLoopCommonModes];
[runloop addTimer:timer forMode: NSEventTrackingRunLoopMode];
编辑:runloop基本上是苹果的循环,用于向应用程序发送任何事件。并根据所谓的模式过滤它调度的事件。
答案 1 :(得分:0)
谢谢大家提出的问题,答案和评论。
使用NSEventTrackingRunLoopMode解决了我不断重绘具有给定参数的OpenGL视图的情况。
class MyOpenGLView: NSOpenGLView {
var timer: Timer?
required init?(coder: NSCoder) {
super.init(coder: coder)
timer = Timer.scheduledTimer(withTimeInterval: 1.0/60, repeats: true) { (t) in
self.needsDisplay = true
}
let runloop = RunLoop.current
runloop.add(timer!, forMode: .commonModes)
// runloop.add(timer!, forMode: .eventTrackingRunLoopMode)
}
override func draw(_ dirtyRect: NSRect) {
// draw moving 3D-cubes
}
}
现在它继续绘图,我拖动滑块来更新其参数。此外,调整窗口的大小变得平滑。
对于其他解决方案&#34;异步进行,&#34;有趣!我稍后会试试。谢谢!
<强>编辑:强>
我已经改变主意使用NSRunLoopCommonModes(RunLoopMode.commonModes),而不是NSEventTrackingRunLoopMode。
两者都运作良好,但Apple的文件暗示共同模式在我的情况下更好。