I am trying to update view every real minute change. I can't find any Notification publishers that can trigger that, so I have an idea to start timer when next minute changing, but I don't really know how to do it( I've tried this code, not seems to work:
.onChange(of: Calendar.current.component(.minute, from: Date())) { _ in
print("Minute has Changed")
if calendarViewModel.isTimerAlreadyPublishing {
print("Timer continue publishing")
} else {
calendarViewModel.startTimer()
}
}
Maybe someone can say more methods how can I accomplish that goal?
You can achieve this with Timer
, starting it when actual minute changes in current time zone and updating view every 60 seconds:
struct ContentView: View {
@State var currentDate = Date()
@State var timer: Timer?
var body: some View {
Text("Current minute: \(currentDate.minute)")
.onAppear {
startMinuteTimer()
}
.onChange(of: currentDate) {_ in
//this is called when every real minute changes in current TimeZone
}
}
private func startMinuteTimer() {
// Get the number of seconds to the next minute
let seconds = 60 - Calendar.current.component(.second, from: .now)
// Set the initial timer to sync with the next minute change
DispatchQueue.main.asyncAfter(deadline: .now() + Double(seconds)) {
self.currentDate = Date()
// After the first trigger, set a timer to repeat every minute
self.timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
self.currentDate = Date()
}
}
}
}
extension Date {
var minute: Int {
return Calendar.current.component(.minute, from: self)
}
}
#Preview {
ContentView()
}