watchOS: Complications

Feb 7 2023 Swift 5.6, watchOS 8.5, Xcode 13

Part 1: Introduction to Complications

4. Support Multiple Families

Episode complete

Play next episode

About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 3. Update a Complication's Data Next episode: 5. Create Templates for Multiple Families

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Pro subscription. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Apple’s Human Interface Guidelines for watchOS contain a wealth of useful material related to complications. For example, you’ll find image size and composition guidance, descriptions of each family type and example images of how the complication family appears on the watch face.

If you’d like to dive deeper into Design Patterns, like the Factory Method design pattern that you implemented in this chapter, please check out our book, Design Patterns by Tutorials.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

We’ve got a functional app with complication support, but it’s pretty limited.

Factory Method design pattern

Consider the code you’ve written so far, and you can likely see some common patterns that you’ll need to replicate across each family.

Current timeline entry

We’ll be generating timeline entries here, so, in this new file, import ClockKit at the top.

import ClockKit
protocol ComplicationTemplateFactory {

  func template(for waterLevel: Tide) -> CLKComplicationTemplate


But what about samples?

func templateForSample() -> CLKComplicationTemplate
extension ComplicationTemplateFactory {
  func templateForSample() -> CLKComplicationTemplate {
    let tide = Tide(entity: Tide.entity(), insertInto: nil) = Date()
    tide.height = 24
    tide.type = .falling

    return template(for: tide)

Tide height text

Right now, your code simply shows the height, but you can do better than that.

func textProvider(for waterLevel: Tide, unitStyle: Formatter.UnitStyle) -> CLKSimpleTextProvider
func textProvider(
  for waterLevel: Tide,
  unitStyle: Formatter.UnitStyle = .short
) -> CLKSimpleTextProvider {

  let shortText = waterLevel.heightString(unitStyle: unitStyle)
  let longText = "\(waterLevel.type.rawValue.capitalized), \(shortText)"
  return .init(text: longText, shortText: shortText)

Tide image

Images are as easy to support as text, but they’ll take two methods. One for full color images, and one for “plain” images. “Plain”, here, just means monochromatic.

func fullColorImageProvider(for waterLevel: Tide) -> CLKFullColorImageProvider
func plainImageProvider(for waterLevel: Tide) -> CLKImageProvider
func fullColorImageProvider(for waterLevel: Tide) -> CLKFullColorImageProvider {
  .init(fullColorImage: waterLevel.image())

func plainImageProvider(for waterLevel: Tide) -> CLKImageProvider {
  .init(onePieceImage: waterLevel.image())