How it works
WidgetConfiguration is the protocol that describes a widget's behavior and presentation — it tells WidgetKit what content a widget shows, what triggers updates, and which contexts and families the widget supports. You return a value conforming to it from the body of your Widget, pairing a kind identifier and a provider with the SwiftUI view that draws each entry, such as the step-count layout built here from Label, Text, and a RoundedRectangle background. Reach for it whenever you define a home-screen, lock-screen, or StandBy widget and need to wire timeline data to a view. You rarely conform to it directly; instead you compose one of the concrete configuration types and refine it with the protocol's modifiers.
Return a
WidgetConfigurationfrom the widget'sbodyA type conforming to
Widgetproduces exactly oneWidgetConfigurationfrom itsbodyproperty, declared assome WidgetConfiguration. That returned value bundles together the widget's identity, its data source, and the view to render — the view here beingWidgetConfigurationDemo, whoseVStackofLabelandTextis the content WidgetKit places in each timeline entry.Choose a concrete configuration type
You don't implement
WidgetConfigurationyourself; you instantiate one of its conforming types.StaticConfigurationdrives a widget from a timeline provider alone, whileAppIntentConfigurationadds user-editable parameters. Both take akindstring and a provider, and return your content view — the samebodyshown inWidgetConfigurationDemo.Restrict supported families with
supportedFamilies(_:)The
supportedFamilies(_:)modifier narrows whichWidgetFamilysizes the system may offer, such as.systemSmallor.accessoryRectangular. Because the demo content is laid out in a fixedframe(width: 150, height: 150), you would constrain the configuration to a small family so the system never asks it to fill a size its layout can't accommodate.Add chrome and metadata modifiers
WidgetConfigurationexposes modifiers that adjust the surrounding container rather than the entry view:configurationDisplayName(_:)anddescription(_:)label the widget in the gallery, andcontainerBackgroundRemovable(_:)andcontentMarginsDisabled()control padding and the system background. These wrap the configuration value, leaving the inner.background(.quaternary, in: RoundedRectangle(cornerRadius: 22))ofWidgetConfigurationDemountouched.Compose configurations with
WidgetBundleEach
WidgetConfigurationrepresents a single widget kind. To ship several widgets from one extension, you list multiple configurations inside aWidgetBundle, where every entry is its own configuration paired with a view likeWidgetConfigurationDemo.
StaticConfiguration and chain .supportedFamilies([.systemSmall, .systemMedium]), then remove .systemMedium to watch the system stop offering the wider size for this widget.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 WidgetConfigurationDemo: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Label("Steps", systemImage: "figure.walk")
.font(.caption)
.foregroundStyle(.secondary)
Text("8,420")
.font(.title.bold())
Text("Goal: 10,000")
.font(.caption2)
.foregroundStyle(.tint)
}
.frame(width: 150, height: 150, alignment: .topLeading)
.padding()
.background(.quaternary, in: RoundedRectangle(cornerRadius: 22))
.padding()
}
}