Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JadenGeller/4b9c91427c6022823fe0c1b2b56aa546 to your computer and use it in GitHub Desktop.
Save JadenGeller/4b9c91427c6022823fe0c1b2b56aa546 to your computer and use it in GitHub Desktop.
update view daily at particular time, or any other date-based interval
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