I want to implement a countdown timer, based on the current time and end time.
For example:
Current time: 20:30:30
End time always is : 23:59:59
-> I will implement a countdown timer as: 03:29:29
A better way is to do the date math with DateComponents
, there is an API dateComponents(_:from:to:)
where from
and to
can be DateComponents
struct TimerView: View {
@State private var differenceComponents = DateComponents()
private let endDateComponents = DateComponents(hour: 23, minute: 59, second: 59)
private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
private let calendar = Calendar(identifier: .gregorian)
var body: some View {
HStack(spacing: 12) {
timerStringView(value: differenceComponents.hour ?? 0)
timerStringView(value: differenceComponents.minute ?? 0 )
timerStringView(value: differenceComponents.second ?? 0)
}
.frame(width: 300, height: 34)
.background(Color.gray)
.onReceive(timer) { _ in
updateComponents()
}
.onAppear(perform: updateComponents)
}
func updateComponents() {
let nowComponents = calendar.dateComponents([.hour, .minute, .second], from: .now)
differenceComponents = calendar.dateComponents([.hour, .minute, .second], from: nowComponents, to: endDateComponents)
}
func timerStringView(value: Int) -> some View {
Text(String(format: "%02d", value))
.font(.system(size: 18, weight: .bold))
.foregroundColor(.black)
.background(Color.white)
.cornerRadius(6)
}
}