Widget Families define the sizes your widget supports.
Each size gives you more space to show more information.
The 3 Main Sizes
.systemSmall → 2x2 grid units → one glanceable piece of info
.systemMedium → 4x2 grid units → current state + supporting info
.systemLarge → 4x4 grid units → full dashboard view
Declaring Support
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
You decide which sizes to support.
If you only list .systemSmall → user can only add the small version.
Reading the Current Size
@Environment(\.widgetFamily) var family
WidgetKit injects the current family at runtime.
Use it to switch between different layouts.
From the Project
struct SampleWidgetEntryView: View {
@Environment(\.widgetFamily) var family
var entry: Provider.Entry
var body: some View {
switch family {
case .systemSmall: SmallWidgetView(entry: entry)
case .systemMedium: MediumWidgetView(entry: entry)
case .systemLarge: LargeWidgetView(entry: entry)
default: SmallWidgetView(entry: entry)
}
}
}
One entry view → routes to three completely different layouts
Same data, different presentation per size
How Each Size Was Used in the Project
Small → icon pill + main value + progress bar
one focused piece of info
Medium → left: current session
right: all 5 sessions with checkmarks
split layout via Divider()
Large → header + hero text + big icon
progress bar with percentage
full session list with icon circles + "Now" pill
The default Case
default: SmallWidgetView(entry: entry)
Required by Swift because widgetFamily has other cases
e.g. .systemExtraLarge, .accessoryCircular, .accessoryRectangular
If you don't handle them → fall back to small
Other Families You Can Support
.systemExtraLarge → iPad only, very wide
.accessoryCircular → lock screen / watch, circular
.accessoryRectangular→ lock screen, rectangular bar
.accessoryInline → lock screen, single line of text
Mental Model