WWDC Notes

Meet WidgetKit

Show Apple's description.
Meet WidgetKit: the best way to bring your app’s most useful information directly to the home screen. We'll show you what makes a great widget and take a look at WidgetKit's features and functionality. Learn how to get started creating a widget, and find out how WidgetKit leverages the power of SwiftUI to provide a stateless experience. Discover how to harness your existing proactive technologies to make sure your widget surfaces relevant material. And create a Timeline that ensures your content is always fresh. For more on creating widgets, check out "Build SwiftUI views for widgets" and "The widgets code-along."

Where we can find the new widgets

  • iPhone and iPad Home screens
  • iPhone and iPad Today view
  • macOS Notification Center

What Makes A Great Widget

  • Glanceable: great widgets display the right amount of content
  • Relevant: great widgets display relevant content at the right place and time, this is very important for Smart Stack, too
  • Personalized: great widgets allow configurations and support as many sizes as possible, widget configurations are done via intents
  • Widget are not mini apps: think of the as your app content projection onto the homescreen

How WidgetKit Works

  • All widgets are built in SwiftUI
  • WidgetKit extensions are background extensions that return a series of view hierarchies (a.k.a. views) in a timeline.
  • Our widget extension donates this timeline (with our views) to the Home screen which will present them at the correct time according to the timeline.
  • This way there's no app launch, load etc: the widgets are immediately glanceable
  • Timelines can be refreshed from main app or via scheduled update from the extensions

Defining a Widget

Main concepts:

  • Kind (a custom String): identifies the different widgets that we provide (for example we can have a detail widget display only one object, and a list widget displaying multiple objects)
  • Placeholder: A temporary view WidgetKit uses to render the widget for the first time, generic representation of the widget (without any user data)

Creating a Glanceable Experience

  • Stateless UI
  • No scrolling
  • No videos or animated images
  • Easy tap interactions with deep link into our app

Views, Timelines, and Reloads

Three types of UI we should provide:

  • Placeholder
  • Snapshot: when is where the system needs to quickly display a single entry, our extension should return it as quickly as possible
  • Timelines: basically multiple snapshots combined with a date that tells the system at what time that view should be shown

Reloads

  • Reloads happen when the system wake up the widget to ask for a new timeline for each widget displayed on the device.
  • Reloads make sure that our widget content is always up-to-date for our user

TimelineProvider Definition

public protocol TimelineProvider {
    associatedType Entry: TimelineEntry
    typealias Context = TimelineProviderContext

    func snapshot(with context: Self.Context, 
                    completion: @escaping (Self.Entry) -> ())

    func timeline(with context: Self.Context, 
                    completion: @escaping (Timeline<Self.Entry>) -> ())

}
  • TimelineEntry: mainly a date.
  • Context: environment information for which the system is asking us for entries.
  • snapshot function: the system is asking us for a single entry (to be returned as soon as possible)
  • Timeline function: the system is asking us for series of entries and attached reload policy (a.k.a. when we want the system to ask for a new timeline)

Timeline Reload policy

When our extension TimelineProvider is asked to provide a Timeline, we also need to define our reload policy:

  • atEnd: tells WidgetKit to request a new timeline only after the date of the last entry has passed
  • after(date: Date): tells WidgetKit to request a new timeline only after a specified date
  • Never: tells WidgetKit to never request a new timeline, the app will let WidgetKit know when a new timeline is available

Reloding via app

  • We can ask the system to reload a specific widget or all widget kinds.
  • We can use URLSession to kick off a task and use batch request as well background session to reload our widgets.

Personalization and Intelligence Aspects

  • Driven by two major contexts:
    • Intents: used as a mechanism to allow users to configure our widget
    • Relevance: which allows us to inform the intelligence in the widget stack.
  • Intents are powered by the Intents framework, the same used with Siri and Shortcuts
  • The widget relevance is particularly useful when the user has multiple widgets into a smart stack: the stack will be sorted based on each entry TimelineEntryRelevance, duration, and more

Missing anything? Corrections? Contributions are welcome 😃

Related

Written by

abadikaka

Michael Abadi Santoso

Michael Abadi is an enthuastic iOS Engineer from Indonesia (working in Bangkok) with love and grit passion for Swift and design pattern. He can be found writing at medium also he is a seasoned writer for Mac O'Clock in Medium recently. He also loves photography and/or playing FIFA and wait someone to beat him in FIFA.

zntfdr

Federico Zanetello

Federico Zanetello is an iOS Engineer with strong passion for Swift, minimalism, and design. When he’s not busy automating things, he can be found writing at fivestars.blog and/or playing with the latest shiny toys.