How have watch complications moved from ClockKit to WidgetKit, and what are accessory families and the Smart Stack?

19.6.3 · L5 · Interview

Predict first

A team already has an iPhone Lock Screen widget with circular, rectangular and inline families. What is the smallest path to a watch complication?

// A: rewrite it in ClockKit
// B: add the watch target to the widget extension and reuse the accessory families and views
// C: build a separate UIKit app
  • A
  • B
  • C

Mental model. A complication is a tiny window cut into the watch face that shows one fact. ClockKit gave you a fixed set of window shapes and a form to fill in; WidgetKit lets you draw the window’s contents yourself, with the same drawing tools you use for a phone widget.

A complication is a small piece of your app’s data on the watch face. The legacy model (watchOS 2 to 8) was ClockKit: a CLKComplicationDataSource in the watch app extension supplied CLKComplicationTemplates (fixed layouts for each family: modular small, circular small, graphic corner…) and a timeline of entries, with the system asking for them and your app extending the timeline with background refresh or transferCurrentComplicationUserInfo. Since watchOS 9 complications are built with WidgetKit: the same Widget, TimelineProvider and SwiftUI views as iPhone widgets, in a widget extension on the watch, using the accessory families that are shared with the iPhone Lock Screen: .accessoryCircular (a small round gauge or icon), .accessoryRectangular (a few lines of text and a chart), .accessoryInline (one line of text along the face) and .accessoryCorner (watchOS only, curved text and a gauge). They have the raw family values 6, 7 and 8 for circular, rectangular and inline, and the view reads @Environment(\.widgetFamily) to adapt. ClockKit is deprecated; new complications should use WidgetKit, which also means one codebase for the iPhone Lock Screen widget and the watch complication, with accessory rendering modes (widgetRenderingMode: full colour on some faces, tinted accented or vibrant on others) that your design must handle (use widgetAccentable() to mark the parts that take the tint, and avoid relying on colour alone).

The same timeline rules as iPhone widgets apply, with a stricter budget and tiny memory: provide many future entries in one timeline, use .atEnd or .after sparingly, and refresh from the watch app with WidgetCenter.shared.reloadTimelines(ofKind:) after background refresh or data arrival (including a Watch Connectivity application-context update). Data comes from the shared app-group container on the watch or from the server through the widget provider’s own network call (a short one). The Smart Stack (watchOS 10) is a scrollable stack of widgets on the watch that surfaces the most relevant ones; supply TimelineEntryRelevance scores and relevance intents (location, time, an activity) so the system promotes yours at the right moment, and use AppIntentConfiguration for user-configurable ones. Complications are also where Live Activities from the iPhone appear on a watch (automatically mirrored) in recent releases. Guidance: design each family to be glanceable in under a second, test on every face type and rendering mode, handle missing data with a meaningful placeholder, and tap targets deep-link into the watch app with widgetURL. A watch complication is the watch equivalent of a widget: if you ship a widget, extending it to the accessory families is usually a small change.

Accessory families are shared across the Lock Screen and the watch, so the same WidgetKit views can usually be reused on watchOS 9 and later.

Common traps

  • Starting a new complication on ClockKit. It is deprecated; use WidgetKit accessory families.
  • Relying on colour in accessory widgets. Many faces tint them; use widgetAccentable() and check the rendering mode.

They might follow up with

  • Which families do the iPhone Lock Screen and the watch share? The accessory families: circular, rectangular and inline (corner is watch-only).
  • How does the Smart Stack decide what to show? From relevance scores and relevance intents the widget provides.

Related questions

  • 19.4.1 How does a WidgetKit widget work: providers, timeline entries, reload policies, families and the refresh…
  • 19.6.2 How does Watch Connectivity work: the transfer types, reachability, and how do you choose between them?

← How does Watch Connectivity work: the transfer types, reachability…