【问题标题】:NSTimer not firing when NSMenu is open in Swift在 Swift 中打开 NSMenu 时,NSTimer 不会触发
【发布时间】:2015-03-15 20:33:01
【问题描述】:

我有一个计时器,它会在闹钟响起后重新启动。

alarm = NSTimer.scheduledTimerWithTimeInterval(
    60 * minutesConstant + secondsConstant,
    target:self,
    selector: Selector("endSession"),
    userInfo: nil,
    repeats:false)

它的选择器函数设置一个模式标志,并使用新的分钟和秒常量调用设置警报的原始函数,并且还向用户发送会话已重新启动的通知。

我有一个菜单项会随着剩余时间更新

所以我一直在打开它以检查我的闹钟确实重新启动,并且一旦它达到零,通知就会显示。它可以工作,但是当我打开菜单并且它降为零时,它只会停留在 0:00 并且计时器不会触发,直到我单击菜单,此时它会立即显示通知并按预期重置计时器.

如何在菜单打开时强制计时器触发?这没什么大不了的,但我不希望用户对会话感到困惑,如果他们看到计时器下降,会话就会挂起。

【问题讨论】:

    标签: xcode macos swift nstimer nsrunloop


    【解决方案1】:

    您只需将计时器添加到主运行循环,如下所示:

    Swift 4.2

    RunLoop.main.add(timer, forMode: .common)
    

    斯威夫特 3

    RunLoop.main.add(alarm, forMode: .commonModes)
    

    Swift 2.x

    NSRunLoop.mainRunLoop().addTimer(alarm, forMode: NSRunLoopCommonModes)
    

    【讨论】:

    • 这是正确的。这基本上就是您在机场菜单中看到的内容,因为它会定期扫描 SSID
    • 特别是在菜单跟踪期间运行循环在NSEventTrackingRunLoopMode中运行。如果您的计时器仅在NSDefaultRunLoopMode 中,它将不会触发。这两种模式都在NSRunLoopCommonModes 集合中,因此将计时器添加到该伪模式允许它在两种情况(和其他情况下)触发。
    • 完美,感谢您的回复和清晰的解释!
    • 在 Swift 3 中这是正确的解决方案:RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
    • 我正在试验我的应用程序(我已将其导出并作为普通应用程序运行)。我发现当我让我的应用程序在后台运行时使用计时器不正确 - 它开始延迟工作,并且在一段时间后 - 冻结。看来这个解决方案行不通。
    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 2023-03-22
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多