我在 macos 中有一个非常简单的应用程序,它运行 NSTimer 来更新值并将其显示在我的 NSView 上的 NSTextField 上。 NSView还包含NSButtons和NSSliders,与该计时器无关。 当我在 NSButton 或 NSSlider 上按住鼠标按钮时,计时器不再更新,直到我抬起鼠标按钮(然后计时器恢复)。 如何防止鼠标按钮事件冻结计时器? 谢谢!
当我在 NSButtons 和 NSSliders 上按住鼠标按钮时,计时器不应冻结
这是您用于计时器的运行循环模式的问题。当用户与滑块交互时,“默认”运行循环模式将冻结。例如,在 Objective-C 中:
- (void)startUpdatingDefaultRunMode {
[NSTimer scheduledTimerWithTimeInterval:0.02 repeats:true block:^(NSTimer * _Nonnull timer) {
self.label.stringValue = [self.dateFormatter stringFromDate:[NSDate now]];
}];
}
或者斯威夫特:
func startUpdatingDefaultRunMode() {
Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { [weak self] _ in
guard let self else { return }
label.stringValue = dateFormatter.string(from: .now)
}
}
但是如果您使用“常见”运行循环模式,它将继续触发。在 Objective-C 中:
- (void)startUpdatingCommonRunMode {
NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:0.02 repeats:true block:^(NSTimer * _Nonnull timer) {
self.label.stringValue = [self.dateFormatter stringFromDate:[NSDate now]];
}];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
或者斯威夫特:
func startUpdatingCommonRunMode() {
let timer = Timer(fire: .now, interval: 0.02, repeats: true) { [weak self] _ in
guard let self else { return }
label.stringValue = dateFormatter.string(from: .now)
}
RunLoop.main.add(timer, forMode: .common)
}
结果: