WWDC Quick Look 💓 By SwiftGGTeam
Meet WidgetKit

Meet WidgetKit

Watch original video

Highlight

WidgetKit uses SwiftUI and timeline mechanisms in iOS 14 to pre-deliver app content to the system, allowing the home screen, Today View, iPad home screen, and macOS Big Sur notification center to display information cards that can be read at a glance and clicked to jump back to the app.

Core Content

Space on the Home Screen is expensive. Users return to the home screen many times a day, staying only for a few seconds at a time. A small-sized widget only has an area of ​​about four icons. If buttons, scrolling lists, or complex controls are stuffed inside, users will leave before they understand it.

This is also the starting point of WidgetKit. Apple defines widgets as content projections that can be glanced at, rather than as small apps that run continuously. The content is the focus, and clicking only brings the user back to the main App; in the small size, the entire widget has only one tap target. When it comes to medium and large, SwiftUI’s Link can allow different areas to enter different locations. (01:50, 12:27)

The new system capabilities solve two old problems. First, the widget does not need to wait for the App process to start before drawing the interface. The WidgetKit extension returns a set of SwiftUI views with time in the background. The system saves these view hierarchy according to timeline and displays them at the correct time. Second, the same pre-prepared content can also be used by the Widget Gallery, and what the user sees before adding is the actual widget status. (05:44, 13:23)

WidgetKit also builds relevance and personalization into the model. Smart Stacks will use on-device intelligence to automatically move appropriate widgets to the top; developers can use Siri Shortcuts donations to help the system understand user habits, and can also provide relevance on timeline entries. The configuration is left to Intents. The system can automatically generate an editing interface from Intents. Users can select cities, stocks or other parameters by long pressing the widget. (02:51, 04:05, 21:13

Therefore, the first step in making WidgetKit is not to write a reduced version of the home page. A more stable path is to first find out the information in the app that is most suitable for being read at a glance, and then decide its size, update time, click point and whether it needs to be configured.

Detailed Content

Define a widget kind

(08:10) A widget definition consists of kind, configuration, supportedFamilies and placeholder. kind allows an extension to support multiple widget types; StaticConfiguration is suitable for scenarios that do not require user configuration; placeholder can only display the representative content of this widget type and cannot contain user data.

@main
public struct SampleWidget: Widget {
    private let kind: String = "SampleWidget"

    public var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind,
                            provider: Provider(),
                            placeholder: PlaceholderView()) { entry in
                                SampleWidgetEntryView(entry: entry)
                            }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

Key points:

  • @main marks the entry point of the widget extension.
  • kind is a string used by the system to identify this type of widget.
  • provider is responsible for providing snapshot and timeline.
  • placeholder is the default display content and is only occasionally requested by the system.
  • configurationDisplayName and description will appear in the interface for adding widgets.

Use timeline to drive display

(13:13) WidgetKit’s running model is divided into three types of UI: placeholder, snapshot and timeline. Snapshot is used to quickly return an entry. Widget Gallery usually displays a preview of the real widget. The timeline is a set of entries and dates that tell the system which view should be displayed at each point in time.

public struct Provider: TimelineProvider {

    public func snapshot(with context: Context,
                         completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date())
        completion(entry)
    }

    public func timeline(with context: Context,
                         completion: @escaping (Timeline<Entry>) -> ()) {
        let entry = SimpleEntry(date: Date())
        let timeline = Timeline(entries: [entry, entry], policy: .atEnd)
        completion(timeline)
    }
}

Key points:

  • snapshot returns a single entry, aiming to be fast.
  • timeline returns the entry array and reload policy.
  • .atEnd indicates that the system requests the next timeline after the timeline ends.
  • transcript also mentioned that you can specify a certain date to reload, or you can tell the system not to reload.
  • The timeline entry will be serialized to disk by the system, and there is no need to start the app’s launcher process when the home screen is displayed.

Control refresh, no real-time running experience

(15:03) reload is the time when the system wakes up the extension and requests a new timeline. The system will refer to the reload policy, widget viewing frequency and device environment changes. When the App receives a background notification, or the user makes changes in the foreground App that will affect the widget, it can request a refresh through WidgetCenter.

Key points:

  • A common timeline should cover several days, rather than just returning the current moment.
  • Widgets that are viewed frequently will get more reloads, and widgets that are viewed less often will get less reloads.
  • WidgetCenter can reload according to kind, can reload the entire timeline, and can also read the current configuration list.
  • When you need to access the server, you can use background URLSessions, and the results are handed over to the extension through onBackgroundURLSessionEvents.
  • Background processing and network have system budget, and widgets are not suitable for updating every second.

Use Intents for configuration

(18:50) If the widget needs to be personalized, WidgetKit uses Intents to carry the configuration. The city of the Weather widget and the stock symbol of the Stocks widget are typical parameters. iOS 14 also allows Intents to support in-app Intent handling, and the App can directly answer questions in the configuration interface.

@main
public struct SampleWidget: Widget {
    private let kind: String = "SampleWidget"

    public var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind,
                    intent: ConfigurationIntent.self
                            provider: Provider(),
                            placeholder: PlaceholderView()) { entry in
                                SampleWidgetEntryView(entry: entry)
                            }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

Key points:

  • IntentConfiguration replaces StaticConfiguration.
  • ConfigurationIntent.self lets the system know what type of Intent parameters this widget uses.
  • When the user edits the widget, the system automatically generates a configuration interface based on the Intent.
  • If a parameter requires dynamic options, the Intents extension or App can return candidate values.

Let timeline receive configuration and relevance

(20:54) After configuring the timeline, the provider must also be replaced with IntentTimelineProvider. The timeline method will receive configuration, and developers use these Intent parameters to generate corresponding entries. Smart Stack relevance uses Shortcuts donations and TimelineEntryRelevance to help the system determine when to move the widget to the top.

public struct Provider: IntentTimelineProvider {

    public func timeline(for configuration: ConfigurationIntent, with context: Context,
                         completion: @escaping (Timeline<Entry>) -> ()) {
        let entry = SimpleEntry(date: Date(), configuration: configuration)

        // generate a timeline based on the values of the Intent

       completion(timeline)
    }
}

Key points:

  • timeline(for:with:completion:) will get the configuration selected by the user.
  • entry can save this configuration and use it to determine the display content.
  • If the same INIntent is used behind the widget, and the user donates Shortcuts after performing relevant actions in the app, there is a chance to help Smart Stack judge the timing.
  • TimelineEntryRelevance can provide score and duration; the score is interpreted relative to the entries provided by the developer in the past.

Core Takeaways

  • What to do: Make the most frequently opened information in the App into a small widget. Why it’s worth doing: Transcript repeatedly emphasizes that the small size only has about four icon areas, and the user’s stay time is very short. Best for single facts like the weather, next meeting, and today’s progress. How ​​to start: First make a StaticConfiguration, write a SwiftUI view that only displays core numbers or status, and then use widgetURL to bring the click back to the corresponding page.

  • What to do: Generate an all-day timeline for time-sensitive content such as schedules, training, and to-dos. Why it’s worth doing: The core capability of WidgetKit is to return entries with time in advance, and the system displays them according to time. The example of Calendar shows that the extension can prepare views before the meeting, during the meeting, and after the next meeting in advance. How ​​to start: Implement TimelineProvider, generate entries at several key time points in the future, and first use .atEnd or the reload policy of the specified date to verify the refresh rhythm.

  • What to do: Add Intent configuration to the widget with selectable content. Why it’s worth doing: The Weather and Stocks examples are both from transcript. Users can select cities, stocks or lists in the widget editing interface, and the system will automatically generate UI using Intent. How ​​to start: Change the widget definition from StaticConfiguration to IntentConfiguration, then let the provider implement IntentTimelineProvider, and use configuration to generate different timelines.

  • What: Let Smart Stack display your widgets at the right time. Why it’s worth it: Smart Stacks will automatically move related widgets to the top. Siri Shortcuts donations and TimelineEntryRelevance both give the system more signals. How ​​to get started: Donate Shortcuts when users complete repeatable actions; set relevance score and duration for timeline entries with clear expiration dates.

Comments

GitHub Issues · utterances