4️⃣Configuring Widgets

Fall 2023 | Reade Plunkett


AppIntents is the framework developed by Apple that allows us to configure our widgets with custom information provided by the user.

Creating a New Intent

We will create a new intent that allows the user to input a location and have the weather widget update its displayed conditions.

Let’s start by creating a new Swift file, which we will call LocationAppIntent.

Within that file, we will define a new structure that conforms to the WidgetConfigurationIntent protocol. This protocol provides us with an interface for configuring a WidgetKit widget.

import WidgetKit
import AppIntents

struct LocationAppIntent: WidgetConfigurationIntent {


This protocol requires us to implement a title for this Intent. Additionally, we can also implement a description on what this intent does.

static var title: LocalizedStringResource = "Location"
static var description = IntentDescription("Enter a location to view the weather.")

Next, we can define a parameter for this intent with a default value. The parameter will contain the location that use inputs.

@Parameter(title: "Location", default: "Ithaca, NY")
var location: String

Changes to WeatherEntry

Since our intent can make changes to a widget entry within our timeline, we must include it inside of the WeatherEntry model.

import WidgetKit

struct WeatherEntry: TimelineEntry {
    let date: Date
    let weather: Weather
    let configuration: LocationAppIntent

Changes to WeatherTimelineProvider

We must also update our timeline provider to support this new app intent. We will change our provider to conform to the AppIntentTimelineProvider protocol to do so.

struct Provider: AppIntentTimelineProvider {


Additionally, we will need to update the function headers for fetching a snapshot and timeline entry.

func snapshot(for configuration: LocationAppIntent, in context: Context) async -> WeatherEntry {

func timeline(for configuration: LocationAppIntent, in context: Context) async -> Timeline<WeatherEntry> {


These two functions provide us with the intent called configuration that contain user-customized values for the location.

Within both of these functions, we have to update our WeatherEntry instantiation to pass in the configuration.

let entry = WeatherEntry(date: Date(), weather: possibleWeathers.randomElement()!, configuration: configuration) 

Additionally, we also have to update the entry created within our placeholder function with a new intent object.

func placeholder(in context: Context) -> WeatherEntry {
    return WeatherEntry(date: Date(), weather: .sunny, configuration: LocationAppIntent())

Changes to Widget Configuration

Within WeatherWidget.swift, we also have to change our widget’s configuration from StaticConfiguration to AppIntentConfiguration.

AppIntentConfiguration(kind: kind, intent: LocationAppIntent.self, provider: Provider()) { entry in
    WeatherWidgetView(entry: entry)

Changes to View

Finally, within WeatherWidgetView, we can update the “Ithaca, NY” string to display the location passed in through the app intent associated with the timeline entry being displayed.

HStack {
        .font(.system(size: 18, weight: .semibold))

Additionally, to view the widget in the Preview window, we will need to provide it with a default configuration. We can define a default intent as an extension of our LocationAppIntent within our view. Since we do not want this default value being used anywhere outside this file, we mark it with fileprivate.

extension LocationAppIntent {
    fileprivate static var cupertino: LocationAppIntent {
        let intent = LocationAppIntent()
        intent.location = "Cupertino, CA"
        return intent

We then update the preview entries to use this new configuration.

#Preview(as: .systemSmall) {
} timeline: {
    WeatherEntry(date: .now, weather: .sunny, configuration: .cupertino)
    WeatherEntry(date: .now, weather: .cloudy, configuration: .cupertino)
    WeatherEntry(date: .now, weather: .overcast, configuration: .cupertino)
    WeatherEntry(date: .now, weather: .rainy, configuration: .cupertino)
    WeatherEntry(date: .now, weather: .lightning, configuration: .cupertino)
    WeatherEntry(date: .now, weather: .snowy, configuration: .cupertino)

Last updated