One Logo Pool Ball
WidgetKit · IOS API REFERENCE

TimelineProvider

protocol · iOS 14.0+ · SDK 27.1

protocol TimelineProvider

A type that advises WidgetKit when to update a widget's display. At various times, WidgetKit requests a _timeline_ from the provider. A timeline is an array of objects conforming to <doc:TimelineEntry>. Each timeline entry has a date, and you can specify additional properties for displaying the widget. For example, consider a widget that displays the health level of a game character. In the game, when the character's health level is below 100 percent, it recovers at a rate of 25 percent per hour. If the character's health level is 25 percent, the provider creates a timeline consisting of the following entries: ![A diagram showing a timeline with four entries, starting with the current time at 25 percent health, and hourly entries for the next three hours at 50, 75, and 100 percent health](TimelineProvider-TimelineEntries.png) The following code shows the structure encapsulating this information. struct CharacterDetailEntry: TimelineEntry { var date: Date var healthLevel: Double } WidgetKit asks for timeline entries in one of two ways: * A single immediate snapshot, representing the widget’s current state. * An array of entries, including the current moment and, if known, any future dates when the widget’s state will change. WidgetKit makes the snapshot request when displaying the widget in transient situations, such as when the user is adding a widget. WidgetKit provides a `context` parameter that includes details about how to use the entry, including whether it’s a preview for the widget gallery, and the family, or size, of the widget to display. If `context.isPreview` is `true`, the widget appears in the widget gallery and requires a quick response from your provider. If the information you need to generate the snapshot is not readily available, or requires additional time to load, use sample data instead. For example, if determining the character's health level requires fetching data from a server, the widget could show the health level at 75 percent. The following code shows how the game widget might implement its snapshot method. struct CharacterDetailProvider: TimelineProvider { func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) { let date = Date() let entry: CharacterDetailEntry if context.isPreview && !hasHealthLevel { entry = CharacterDetailEntry(date: date, healthLevel: 0.75) } else { entry = CharacterDetailEntry(date: date, healthLevel: currentHealthLevel) } completion(entry) } } WidgetKit makes the timeline request after the user adds your widget from the widget gallery. Because your widget extension is not always running, WidgetKit needs to know when to activate it to update the widget. The timeline your provider generates informs WidgetKit when you would like to update the widget. The following example shows how the <doc://com.apple.documentation/documentation/widgetkit/emoji-rangers-supporting-live-activities-interactivity-and-animations> sample code project creates a timeline for its leaderboard widget. func getTimeline(in context: Context, completion: @escaping (Timeline<LeaderboardEntry>) -> Void) { EmojiRanger.loadLeaderboardData { (heros, error) in guard let heros else { let timeline = Timeline(entries: [LeaderboardEntry(date: Date(), heros: EmojiRanger.availableHeros)], policy: .atEnd) completion(timeline) return } let timeline = Timeline(entries: [LeaderboardEntry(date: Date(), heros: heros)], policy: .atEnd) completion(timeline) } } If your provider needs to do asynchronous work to generate the timeline, such as fetching data from a server, store a reference to the `completion` handler and call it when you are done with your asynchronous work. ### Determine a refresh policy When creating the timeline, the provider specifies a refresh policy that controls when WidgetKit requests a new timeline. The default behavior is to use ``WidgetKit/TimelineReloadPolicy/atEnd`` to request a new timeline after the last date specified by the entries in a timeline. However, if there is a different date when WidgetKit should request a new timeline, you can specify a refresh policy of ``WidgetKit/TimelineReloadPolicy/after(_:)``. For example, a dragon will appear in 2.5 hours and might engage in battle with the game character. Because the outcome of this battle may change the character's health level, the provider can tell WidgetKit to request a new timeline after the battle. // Request a timeline refresh after 2.5 hours. let date = Calendar.current.date(byAdding: .minute, value: 150, to: Date())! let timeline = Timeline(entries: entries, policy: .after(date)) completion(timeline) Other examples of when it makes sense to use a different date include: * In a widget displaying stock market details, you might specify the next market opening or closing date because information typically doesn't change overnight or during weekends. * A flight tracking widget might continue showing a “flight landed” indication after the flight lands. In this case, you could specify a date later than when the flight lands so that its status remains visible for a while before being cleared. Alternatively, if future events are unpredictable, you can tell WidgetKit to not request a new timeline at all by specifying ``WidgetKit/TimelineReloadPolicy/never`` for the policy. In that case, your app calls the <doc:WidgetCenter> function <doc:WidgetCenter/reloadTimelines(ofKind:)> when a new timeline is available. Some examples of when using ``WidgetKit/TimelineReloadPolicy/never`` makes sense include: * When the user has a widget configured to display the health of a character, but that character is no longer actively engaging in battle and its health level won't change. * When a widget’s content is dependent on the user being logged into an account and they aren’t currently logged in. In both examples, when your app determines that the status has changed, it calls the <doc:WidgetCenter> function <doc:WidgetKit/WidgetCenter/reloadTimelines(ofKind:)> and WidgetKit requests a new timeline. ### Refresh widgets efficiently Each configured widget receives a limited number of refreshes every day. Several factors affect how many refreshes a widget receives, such as whether the containing app is running in the foreground or background, how frequently the widget is shown onscreen, and what types of activities the containing app engages in. - Note: WidgetKit does not impose this limit when debugging your widget in Xcode. To verify that your widget behaves correctly, test your app and widget's behavior outside of Xcode's debugger. Use the following approaches to optimize your widget refreshes: * Have the containing app prepare data for the widget in advance of when the widget needs it. Use a shared group container to store the data. * Use background processing time in your app to keep shared data up to date. For more information, see <doc://com.apple.documentation/documentation/uikit/using-background-tasks-to-update-your-app>. * Choose the most appropriate refresh policy for the information being shown, as described in the preceding section. * Call <doc:WidgetCenter/reloadTimelines(ofKind:)> only when information the widget is currently displaying changes. When your app is in the foreground, has an active media session, or is using the standard location service, refreshes don't count against the widget's daily limit. For more information about media sessions and location services, see <doc://com.apple.documentation/documentation/avfaudio/avaudiosession> and <doc://com.apple.documentation/documentation/corelocation/configuring-your-app-to-use-location-services>.

Members (1)

method · iOS 18.0+

relevance

Swift declaration
func relevance() async -> WidgetRelevance<Void>

Provides an object containing attributes that describe when a specific widget is relevant. The system can use the relevance to show this widget in the Smart Stack when the provided relevance matches a person's context. For example, if you indicate relevance at a specific location, the system could show the widget when a person is at or close to the location. By default, this method returns no relevances. Implement this requirement to tell the system that your widget is relevant. > Note: Smart Stacks are available in iOS, iPadOS, and watchOS. However, functionality provided by RelevanceKit API is only available in watchOS. Calling its API on other platforms doesn't have any effect. For more information, refer to <doc:Widget-Suggestions-In-Smart-Stacks>. - Returns: The object that contains attributes that describe when a specific widget is relevant.

Skipped declarations

No declarations were skipped in this snapshot.

All WidgetKit types →