TechnologiesSwiftUI

Widget protocol

iOSmacOStvOSwatchOSvisionOS✓ renders

The configuration and content of a widget to display on the Home screen or

How it works

A widget is the configuration for a glanceable piece of your app's content that the system displays on the Home Screen, in the Today View, on the Lock Screen, or in other widget surfaces. You conform a type to Widget to declare that configuration — its kind, its supported families, and the SwiftUI view that draws each entry of timeline data. Reach for Widget when you want to surface timely, at-a-glance information outside your app, without the user opening it. The protocol is the entry point that ties a widget's identity, its configuration, and its view together into something the system can install and refresh.

  1. Conform a type to Widget and provide a configuration

    A Widget is a value type whose single requirement is a body of type some WidgetConfiguration. The system asks for that configuration to learn the widget's identity and how to build its content. The view shown for each timeline entry is an ordinary SwiftUI view hierarchy — the same kind you see in the accompanying WidgetDemo, where a VStack of Text and Image lays out an "Up Next" card.

  2. Choose a configuration kind

    Inside body you return either a StaticConfiguration, for widgets with no user-set parameters, or an AppIntentConfiguration, for widgets the user can customize by editing. The configuration is initialized with a kind string that uniquely identifies the widget within your app, plus a provider that supplies timeline entries and a closure that renders each entry into a view like the card built in WidgetDemo.

  3. Drive content from a TimelineProvider

    The configuration's provider conforms to TimelineProvider (or AppIntentTimelineProvider) and produces dated entries that tell the system what to show and when to refresh. Each entry is handed to your view-building closure, so values such as the Text("Team Standup") event title and the Text("10:00 AM") time would come from the current entry rather than being hard-coded as they are in the demo.

  4. Declare supported families and metadata with modifiers

    Apply modifiers to the returned configuration to describe where and how the widget appears: supportedFamilies(_:) lists sizes like .systemSmall or .systemMedium, while configurationDisplayName(_:) and description(_:) provide the title and subtitle shown in the widget gallery. The fixed .frame(width: 160, height: 160) in WidgetDemo stands in for the system-sized frame a real widget family would impose.

  5. Register the widget in a WidgetBundle

    A Widget type does not run on its own — you expose it through a @main type conforming to WidgetBundle, listing each Widget in the bundle's body. This is how the system discovers your widgets and offers them for the user to add to a widget surface, where the card laid out in WidgetDemo would finally be drawn.

Try it — Change the hard-coded Text("10:00 AM") in WidgetDemo to read from a timeline entry's date so the widget shows a value that updates as the system refreshes it, demonstrating how Widget content is driven by its provider rather than fixed in the view.

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.

Widget.swift
struct WidgetDemo: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                Image(systemName: "calendar")
                    .foregroundStyle(.red)
                Text("Up Next")
                    .font(.caption)
                    .foregroundStyle(.secondary)
                Spacer()
            }
            Text("Team Standup")
                .font(.headline)
            Text("10:00 AM")
                .font(.title2.bold())
                .foregroundStyle(.blue)
        }
        .padding()
        .frame(width: 160, height: 160)
        .background(.regularMaterial)
        .clipShape(RoundedRectangle(cornerRadius: 20))
        .padding()
    }
}
Live preview
Up Next Team Standup 10:00 AM
Up Next Team Standup 10:00 AM
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →