斯威夫特 - 不工作
包涵scheduledTimer秒表小时部分我拿起斯威夫特和Xcode的一个星期前(IM创建一个应用程序在我的假期学习斯威夫特)斯威夫特 - 不工作
我使用scheduledTimer充当秒表创建一个定时器。秒和分钟运行良好,但我无法获得工作时间。我究竟做错了什么?
currentTime = 0
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
self.currentTime += 1
let hoursPortion = String(format: "%02d", CGFloat(self.currentTime) * 60)
let minutesPortion = String(format: "%02d", self.currentTime/60)
let secondsPortion = String(format: "%02d", self.currentTime % 60)
//let tenPortion = String(format: "%d", self.currentTime * 10 % 10)
self.TimerDisplay.text = "\(hoursPortion):\(minutesPortion):\(secondsPortion)"
}
这不是最好的方法,因为定时器不能保证足够准确,它会随着时间而漂移。更好的方法是记录开始时间并使用日历功能为您提供已用时间。例如
let startTime = Date()
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
let now = Date()
let components = Calendar.current.dateComponents([.hour, .minute, .second], from: startTime, to: now)
guard let hoursPortion = components.hour, let minutesPortion = components.minute, let secondsPortion = components.second
else {
preconditionFailure("Should not happen")
}
self.TimerDisplay.text = "\(hoursPortion):\(minutesPortion):\(secondsPortion)"
}
感谢您的评论是有用的!我没有最终将它用于我正在进行的项目,但我正在测试一些东西并使其工作。如何格式化计时器以显示00:02:20 2分20秒? –
使用您在初始问题中使用的字符串(格式:)方法,或使用Rob的DateComponentsFormatter建议。 –
正如其他人所说的,你不应该试图自己跟踪时间。让系统判断已经过了多长时间。而且,我会倾向于使用DateComponentsFormatter
格式化字符串也适用于你:
@IBOutlet weak var elapsedLabel: UILabel!
weak var timer: Timer?
private var formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.allowedUnits = [.hour, .minute, .second]
formatter.zeroFormattingBehavior = .pad
return formatter
}()
private func startTimer() {
timer?.invalidate() // stop prior timer, if any
let startTime = Date()
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
self?.elapsedLabel.text = self?.formatter.string(from: startTime, to: Date())
}
}
deinit {
timer?.invalidate()
}
顺便说一句,这是一个微妙的一点,但请注意在Timer
封闭的捕获列表使用[weak self]
。如果没有这个功能,你可以改变一个强参考周期,因为定时器不会停止,直到它们被调用,但视图控制器的deinit
只有在解决了定时器对视图控制器的强引用之后才能被调用。通过在闭包中使用[weak self]
捕获列表,我们打破了这个循环,允许视图控制器在被解除时释放并且它会停止定时器。
如果当前时间已过秒,则小时数为'currentTime/3600'。我不知道你为什么乘以20.这种方法可能不是最好的;计时器不准确。更好的方法是在秒表开始时创建一个“日期”,并在计时器计时时计算该日期与“现在”之间的差值。 'DateComponents'可以帮助您从日期获取字段。 – Paulw11
是的,这是真的20应该是3600,但我把它设置为20,所以我不必等待一个小时,看看它是否工作。我将hoursPortion设置为乘数,因为我认为1小时= 3600秒。 –
不,你想划分,因为1小时= 3600秒;如果'currentTime' = 3600那么这是1小时,所以'currentTime/3600' – Paulw11