How do several widgets live in one extension, and what is a widget’s kind used for?

19.8.3 · L3 · Interview

Predict first

Does a bundle of 16 widgets compile?

import WidgetKit
import SwiftUI

struct E: TimelineEntry { let date: Date }
struct P: TimelineProvider {
    func placeholder(in context: Context) -> E { E(date: .now) }
    func getSnapshot(in context: Context, completion: @escaping (E) -> Void) { completion(E(date: .now)) }
    func getTimeline(in context: Context, completion: @escaping (Timeline<E>) -> Void) {
        completion(Timeline(entries: [E(date: .now)], policy: .never))
    }
}
struct W1: Widget { var body: some WidgetConfiguration { StaticConfiguration(kind: "w1", provider: P()) { _ in Text("1") } } }
struct W2: Widget { var body: some WidgetConfiguration { StaticConfiguration(kind: "w2", provider: P()) { _ in Text("2") } } }

@main struct Bundle16: WidgetBundle {
    var body: some Widget {
        W1(); W2(); W1(); W2(); W1(); W2(); W1(); W2()
        W1(); W2(); W1(); W2(); W1(); W2(); W1(); W2()
    }
}
  • Yes, it compiles
  • No: a bundle is limited to a handful of widgets
  • No: @main is not allowed on a bundle

Mental model. The kind is a widget’s passport number: change it and the system sees a stranger.

One widget extension can hold many widgets through a WidgetBundle, and that bundle is the extension’s @main. Each widget has a kind string passed to its configuration; the system uses it to identify the widget, and your app uses it in WidgetCenter.shared.reloadTimelines(ofKind:). The check compiled a bundle with 16 widgets, so the old “five or six widgets per bundle” limit no longer applies on this toolchain. Choose kinds once and never change them: renaming a kind makes the system treat the widget as a new one, and users who added the old one lose it from their Home Screen.

A typo in the kind passed to reloadTimelines(ofKind:) fails silently, so keep kinds as shared constants and reload from the app through one small helper. Use reloadAllTimelines() sparingly; it counts against the budget for every widget. Widgets, Control Center controls (Q407) and Live Activities can share the same bundle. Not run: how the gallery lists them, which needs a device or simulator UI.

WidgetBundle accepts this many widgets in one builder.

Common traps

  • Renaming a kind in a release. Existing placed widgets disappear.
  • Reloading by a mistyped kind. Nothing reloads and nothing reports it.

They might follow up with

  • Can I find what the user placed? WidgetCenter.shared.getCurrentConfigurations returns the placed widgets, so you can reload only what exists.

Related questions

  • 19.4.1 How does a WidgetKit widget work: providers, timeline entries, reload policies, families and the refresh…
  • 19.4.2 How do configurable widgets, interactive buttons and Control Center controls work with App Intents?
  • 19.7.2 How do you treat extensions, widgets and intents as a public API of the product: shared modules, data…

← How do you unit test a widget’s timeline logic when the provider’s…   How do widgets adapt to the tinted Home Screen and the Lock Screen… →