gpt4 book ai didi

ios - 当时间(iOS 时钟)发生变化时,有什么方法可以运行代码吗?

转载 作者:搜寻专家 更新时间:2023-11-01 07:17:52 25 4
gpt4 key购买 nike

当系统时钟改变时,是否有运行代码的方法?

例如:当时钟增加一分钟时,运行 print(systemtime),我将当前时间存储在该变量中。

这只是为了我自己的测试目的,现在我有一个每分钟重复一次的计时器,获取当前时间并打印它。

但是,我正在寻找一种方法来在 iOS 中打印时间到控制台的确切时间。

在更一般的意义上,一种在 iOS 时钟更改时触发运行代码的方法。

最佳答案

一句话,没有。 iOS 上的实时时钟具有亚微秒精度。它使用 double 来报告自 iOS“纪元日期”以来的小数秒时间。

在任意时间间隔(60 秒,秒)调用函数不是系统函数。

也就是说,您可以设置一个 CADisplayLink (低开销计时器)同步到屏幕刷新,并且当时间在一分钟变化的某个阈值内时“( fmod(NSdate.timeIntervalSinceReferenceDate, 60) < 0.02 ,比方说)您可以将消息记录到控制台。您需要使用阈值,因为您设置的任何间隔可能不会恰好出现在所需的标记上。

编辑

正如马特在下面的评论中指出的那样,CADisplayLink可能会导致设备 CPU“过热”并比预期更快地耗尽电池电量。

如果您不需要毫秒精度,那么做一些数学计算来计算下一分钟的间隔并在适当的延迟后启动重复计时器可能是一个很好的折衷方案。像这样:

var timer: Timer?

func startMinuteTimer() {
let now = Date.timeIntervalSinceReferenceDate
let delayFraction = trunc(now) - now

//Caluclate a delay until the next even minute
let delay = 60.0 - Double(Int(now) % 60) + delayFraction

DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
self.timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
timer in
//Put your code that runs every minute here.
}
}
}

NSTimer(定时器,在 Swift 3 中)的分辨率应该在 1/50 秒左右,因此代码应该使您的更新在目标时间的大约 0.02 秒内。

此外,任何时候您的应用程序变为非事件状态然后再次事件时,您都必须终止上述计时器并重新启动它,因为它会在您的应用程序未运行时暂停并且它不会被同步以启动甚至分钟。

编辑#2:

正如我在回答的评论中所指出的,上面的代码在开始执行后的第一分钟内将无法触发。假设您的类中有一个函数 timeFunction 希望每分钟运行一次,您可以像这样修复它:

  DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
self.timeFunction() //Call your code that runs every minute the first time
self.timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
timer in
self.timeFunction() //Call your code that runs every minute.
}
}

编辑#3:

我在一个示例 iOS 应用程序中使用了上述代码,发现如果您暂停该应用程序(将其切换到后台),则计时器将按预期停止触发。当您恢复您的应用程序时,计时器几乎立即触发,与“即时”时间不同步。然后它会在下一个即时时间再次出现。

为了避免在收到恢复调用时的关闭时间调用,您必须监听挂起和恢复事件,在挂起事件上使您的计时器无效,并在恢复事件上重新创建您的计时器。 (如果不将您的应用程序设置为在后台运行,则无法让它在后台或手机被锁定时每分钟持续触发。)

编辑#4:

这是一个来自工作“单一 View ”应用程序的 View Controller 代码,它完成了所描述的一切:为 willResignActiveNotification 和 didBecomeActiveNotification 添加观察者,启动单次计时器以与分钟的变化同步,然后是重复计时器每一分钟。它有代码在每次计时器触发时将时间显示到标签上,并在每次更新时将时间附加到 TextView ,以便您可以看到行为,并记录暂停/恢复事件。

它有两个导出:

  • timeLabel(显示当前时间的 UILabel)
  • timeTextView:显示时间日志和暂停/恢复事件的 UITextView。
import UIKit

class ViewController: UIViewController {

@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var timeTextView: UITextView!
weak var timer: Timer?
var observer1, observer2: Any?
lazy var timeFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm.ss.SSS"
return formatter
}()

func appendStringToLog(string: String) {
let newTimeLogText = timeTextView.text + "\n" + string
timeTextView.text = newTimeLogText
}

func timeFunction() {
let timeString = timeFormatter.string(from: Date())
timeLabel.text = timeString
appendStringToLog(string: timeString)
print(timeString)
}
func startMinuteTimer() {
let now = Date.timeIntervalSinceReferenceDate
let delayFraction = trunc(now) - now

//Caluclate a delay until the next even minute
let delay = 60.0 - Double(Int(now) % 60) + delayFraction

//First use a one-shot timer to wait until we are on an even minute interval
self.timer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { timer in

//The first time through, call the time function
self.timeFunction() //Call your code that runs every minute the first time

//Now create a repeating timer that fires once a minute.
self.timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
timer in
self.timeFunction() //Call your code that runs every minute.
}
}
}

override func viewDidLoad() {
super.viewDidLoad()

//Observe the willResignActiveNotification so we can kill our timer
observer1 = NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: nil) { notification in
let string = "Suspending. Stopping timer at \(self.timeFormatter.string(from: Date()))"
print(string)
self.appendStringToLog(string: string)
self.timer?.invalidate()
}

//Observe the didBecomeActiveNotification so we can start our timer (gets called on app launch and on resume)
observer2 = NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { notification in
let string = "Becoming active. Starting timer at \(self.timeFormatter.string(from: Date()))"
print(string)
self.appendStringToLog(string: string)
self.startMinuteTimer()
}
}
}

关于ios - 当时间(iOS 时钟)发生变化时,有什么方法可以运行代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40983102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com