如何防止鼠标事件冻结定时器

问题描述 投票:0回答:1

我在 macos 中有一个非常简单的应用程序,它运行 NSTimer 来更新值并将其显示在我的 NSView 上的 NSTextField 上。 NSView还包含NSButtons和NSSliders,与该计时器无关。 当我在 NSButton 或 NSSlider 上按住鼠标按钮时,计时器不再更新,直到我抬起鼠标按钮(然后计时器恢复)。 如何防止鼠标按钮事件冻结计时器? 谢谢!

当我在 NSButtons 和 NSSliders 上按住鼠标按钮时,计时器不应冻结

macos nstimer nstextfield
1个回答
0
投票

这是您用于计时器的运行循环模式的问题。当用户与滑块交互时,“默认”运行循环模式将冻结。例如,在 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)
    }
}

enter image description here

但是如果您使用“常见”运行循环模式,它将继续触发。在 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)
}

结果:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.