使用计时器更新时间时,如何使时间与macOS系统时钟同步?

时间:2019-03-27 17:21:00

标签: swift macos timer clock

我正在使用以下代码在NSLabel中显示时间:

模型

func startClock() {
    timer = Timer(timeInterval: 1.0, target: self, selector: #selector(fireAction), userInfo: nil, repeats: true)
    RunLoop.current.add(timer!, forMode: RunLoop.Mode.common)
    timer?.tolerance = 0.05
    fireAction()
}

@objc dynamic func fireAction() {
    delegate?.timeToUpdateClock(self)
}

ViewController

extension ViewController: ClockWorksProtocol {
    func timeToUpdateClock(_ timer: ClockWorks) {
        tick()
     }
}

 func tick() {
    clockDateLabel.stringValue = DateFormatter.localizedString(from: Date(), dateStyle: .full, timeStyle: .none)
    clockTimeLabel.stringValue = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .medium)
}

一切似乎都运行良好,但不幸的是,显示的秒数与您在菜单栏上的时钟中看到的秒数不同步。我想发生这种情况是因为我每秒更新一次时钟,但是当秒数正确开始时用户不会单击,而是在从一秒到下一秒的间隔内单击(我将timeInterval用作1.0的计时器)

我可以将计时器的timeInterval从1.0秒更改为0.1秒。这似乎可行,但恐怕这会浪费太多资源。

我发布了同时制作的两个屏幕截图。它们显示两个不同的时间(秒):

enter image description here

enter image description here

我如何解决差距?

1 个答案:

答案 0 :(得分:0)

我知道您可以在这里采取两种方法:

  1. 计算从现在到下一秒之间的时间量 dt
let nextSecond = floor(now.timeIntervalSince1970) + 1
let dt = nextSecond - now.timeIntervalSince1970

制作一个计时器,从现在开始正好触发一次 dt。在该计时器的回调中,启动一个以 1 秒为间隔重复的计时器(每次执行 tick()),这正是您的 startClock() 函数所做的。

如果您希望滴答声尽快开始,您也可以在第一个计时器触发时运行 tick()


  1. 确定下一秒将作为日期发生的时刻。

Date(timeIntervalSince1970: floor(Date().timeIntervalSince1970) + 1)

将此 init 用于计时器,它在特定的 fireAt 日期启动它,将其设置为每秒重复一次。

let timer = Timer(fireAt: 
                      Date(timeIntervalSince1970:
                               floor(Date().timeIntervalSince1970) + 1),
                  interval: 1.0,
                  target: self,
                  selector: #selector(fireAction),
                  userInfo: nil, 
                  repeats: true)