Created
July 27, 2025 18:19
-
-
Save JadenGeller/4b9c91427c6022823fe0c1b2b56aa546 to your computer and use it in GitHub Desktop.
update view daily at particular time, or any other date-based interval
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct DateComponentsTimelineSchedule: TimelineSchedule { | |
let components: DateComponents | |
let calendar: Calendar | |
let matchingPolicy: Calendar.MatchingPolicy | |
init( | |
components: DateComponents, | |
calendar: Calendar = .current, | |
matchingPolicy: Calendar.MatchingPolicy = .nextTime | |
) { | |
self.components = components | |
self.calendar = calendar | |
self.matchingPolicy = matchingPolicy | |
} | |
func entries(from startDate: Date, mode: TimelineScheduleMode) -> DateComponentsSequence { | |
DateComponentsSequence( | |
startDate: startDate, | |
components: components, | |
calendar: calendar, | |
matchingPolicy: matchingPolicy | |
) | |
} | |
struct DateComponentsSequence: Sequence, IteratorProtocol { | |
var nextDate: Date? | |
let components: DateComponents | |
let calendar: Calendar | |
let matchingPolicy: Calendar.MatchingPolicy | |
init( | |
startDate: Date, | |
components: DateComponents, | |
calendar: Calendar, | |
matchingPolicy: Calendar.MatchingPolicy | |
) { | |
self.components = components | |
self.calendar = calendar | |
self.matchingPolicy = matchingPolicy | |
// Find the most recent occurrence by searching backward from now | |
// This ensures we always start from a valid point, even if it's in the past | |
self.nextDate = calendar.nextDate( | |
after: startDate, | |
matching: components, | |
matchingPolicy: matchingPolicy, | |
direction: .backward | |
) | |
} | |
mutating func next() -> Date? { | |
guard let current = nextDate else { return nil } | |
// Find next occurrence after current | |
nextDate = calendar.nextDate( | |
after: current, | |
matching: components, | |
matchingPolicy: matchingPolicy | |
) | |
return current | |
} | |
} | |
} | |
extension TimelineSchedule where Self == DateComponentsTimelineSchedule { | |
/// A schedule that updates at dates matching the given DateComponents | |
static func dateComponents( | |
_ components: DateComponents, | |
calendar: Calendar, | |
matchingPolicy: Calendar.MatchingPolicy = .nextTime | |
) -> DateComponentsTimelineSchedule { | |
DateComponentsTimelineSchedule( | |
components: components, | |
calendar: calendar, | |
matchingPolicy: matchingPolicy | |
) | |
} | |
/// A schedule that updates daily at the specified time | |
static func daily(at hour: Int, minute: Int = 0, calendar: Calendar) -> DateComponentsTimelineSchedule { | |
var components = DateComponents() | |
components.hour = hour | |
components.minute = minute | |
components.second = 0 | |
return DateComponentsTimelineSchedule(components: components, calendar: calendar) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment