How it works
TimelineView is a container view that updates its content according to a schedule you provide, redrawing itself at each point on a timeline rather than only when its observed state changes. Reach for it when a view must reflect the passage of time on its own — a clock, a countdown, a progress ring, or an animation that advances at fixed intervals — without you managing a Timer, publisher, or manual state updates. You describe when to refresh by passing a TimelineSchedule, and SwiftUI invokes your content closure at each scheduled instant, handing it a context that carries the current date.
Drive updates with a TimelineSchedule
The first initializer argument is a value conforming to TimelineSchedule that defines the sequence of dates at which the view refreshes. Here
.periodic(from: .now, by: 1)produces a tick once every second starting at the current moment; other schedules include.everyMinute,.animation, and.explicit(_:)for an exact list of dates.Receive the timeline context in the content closure
TimelineView's trailing closure is its ViewBuilder content, called fresh at each scheduled update with a
TimelineViewDefaultContextvalue. The example binds it ascontext, and itscontext.dateproperty holds the date for the current invocation — the source of truth for whatever the view should display at that instant.Build the per-tick content from the context's date
Whatever views you return from the closure are re-evaluated on every tick, so reading
context.datemakes the UI track time automatically. The example feeds it intoText(context.date, style: .time), which renders the live clock face that changes each second as the schedule fires.Compose and style like any other view
TimelineView is itself a View, so it slots into a body and accepts modifiers and child layout as usual — the surrounding
VStackand the trailing.padding()apply to it exactly as they would to any container. The timeline behavior is confined to the schedule and the closure; the rest is ordinary SwiftUI composition.
.periodic(from: .now, by: 1) to .periodic(from: .now, by: 0.1) and watch the Text(context.date, style: .time) clock refresh ten times a second instead of once.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct TimelineViewDemo: View {
var body: some View {
TimelineView(.periodic(from: .now, by: 1)) { context in
VStack(spacing: 8) {
Text("Live Clock")
.font(.headline)
Text(context.date, style: .time)
.font(.system(.largeTitle, design: .monospaced))
.foregroundStyle(.tint)
}
}
.padding()
}
}