[英]How to make a circular timer with Dates in SwiftUI?
我需要一些帮助。 我想出了如何制作一个循环计时器,但不是那样,我想用日期制作它,我的例子是使用 Int 值。 例如,我正在尝试从未来日期(例如:2 月 4 日 11:00 PM)到日期(2 月 4 日 9:00 PM)倒计时。
这是我写的代码:
import SwiftUI
let timer = Timer
.publish(every: 1, on: .main, in: .common)
.autoconnect()
struct CircularTimer: View {
@State var counter: Int = 0
var countTo: Int = 120
var nowDate = Date()
var futureDate = Date.distantFuture
var body: some View {
VStack{
ZStack{
Circle()
.fill(Color.clear)
.frame(width: 250, height: 250)
.overlay(
Circle().stroke(Color.green, lineWidth: 25)
)
Circle()
.fill(Color.clear)
.frame(width: 250, height: 250)
.overlay(
Circle().trim(from:0, to: progress())
.stroke(
style: StrokeStyle(
lineWidth: 25,
lineCap: .round,
lineJoin:.round
)
)
.foregroundColor(
(completed() ? Color.orange : Color.red)
).animation(
.easeInOut(duration: 0.2)
)
)
}
}.onReceive(timer) { time in
if (self.counter < self.countTo) {
self.counter += 1
}
}
}
func completed() -> Bool {
return progress() == 1
}
func progress() -> CGFloat {
return (CGFloat(counter) / CGFloat(countTo))
}
}
我也是 SwiftUI 编程的新手,但我尝试重写您的解决方案以获得所需的 output。 您只需要使用DateComponents ,然后使用TimeInterval ,因为这两个允许您在几秒钟内表示Date()变量,因此您可以轻松地将它用于您的计时器。 这里是:
import SwiftUI
let timer = Timer
.publish(every: 1, on: .main, in: .common)
.autoconnect()
struct CircularTimer: View {
// MARK: Changed type to TIMEINTERVAL
@State var counter: TimeInterval = 0
// MARK: New DATE variables using DATECOMPONENTS
@State var startDate: Date = Calendar.current.date(from: DateComponents(year: 2022, month: 2, day: 4, hour: 11, minute: 00, second: 10)) ?? Date.now
var endDate: Date = Calendar.current.date(from: DateComponents(year: 2022, month: 2, day: 4, hour: 11, minute: 00, second: 00)) ?? Date.now
// MARK: Calculated TIMEINTERVAL instead of original COUNTTO variable
var timeInterval: TimeInterval {
let end = endDate
let start = startDate
return start.timeIntervalSince(end)
}
var body: some View {
NavigationView {
VStack{
ZStack{
Circle()
.fill(Color.clear)
.frame(width: 250, height: 250)
.overlay(
Circle().stroke(Color.green, lineWidth: 25)
)
Circle()
.fill(Color.clear)
.frame(width: 250, height: 250)
.overlay(
Circle().trim(from:0, to: progress())
.stroke(
style: StrokeStyle(
lineWidth: 25,
lineCap: .round,
lineJoin:.round
)
)
.foregroundColor(
(completed() ? Color.orange : Color.red)
).animation(
.easeInOut(duration: 0.2)
)
)
// MARK: Text view for DATE just to show you that timer is working
Text("\(startDate.formatted(date: .long, time: .standard))")
.font(.system(size: 10))
.foregroundColor((timeInterval == 0) ? .orange : .black)
}
}
// MARK: Changed logic for timer calculations
.onReceive(timer) { time in
if (timeInterval != 0) {
counter += 1
startDate -= 1
}
}
// MARK: A few changes to the layout
.navigationTitle("Timer")
.toolbar {
Button("Start again", action: startAgain)
}
}
}
// MARK: Function for a START AGAIN button
func startAgain() {
counter = 0
startDate = Calendar.current.date(from: DateComponents(year: 2022, month: 2, day: 4, hour: 11, minute: 00, second: 10)) ?? Date.now
return
}
func completed() -> Bool {
return progress() == 1
}
func progress() -> CGFloat {
return (CGFloat(counter) / CGFloat(timeInterval + counter))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.