watchOS: Complications

Feb 7 2023 · Swift 5.6, watchOS 8.5, Xcode 13

Part 2: Tinted & Custom Complications

13. Display a SwiftUI View in a Complication

Episode complete

About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 12. Refactor SwiftUI Views

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

Take your career further with a Kodeco Personal Plan. 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.

Notes: 13. Display a SwiftUI View in a Complication

For more information on watchOS development, check out our book watchOS With SwiftUI by Tutorials

For more information about complications, check out these resources:

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

After all of that work, it’s time to wrap this project up and check out your SwiftUI view in a complication.

Event to timeline entry

All the complication methods need to be able to create a CLKComplicationTimelineEntry from an EKEvent.

import EventKit
private func timelineEntry(for ekEvent: EKEvent?) -> CLKComplicationTimelineEntry {

}
  let event: Event?
  if let ekEvent = ekEvent {
    event = Event(ekEvent: ekEvent)
  } else {
    event = nil
  }
  let template = CLKComplicationTemplateGraphicRectangularFullView(
    EventComplicationView(event: event)
  )
  return .init(
    date: event?.startDate ?? .now,
    complicationTemplate: template
  )
}

Localizable sample

As we learned earlier in the course, it’s important to have a sample complication for users to see when they’re choosing complications.

func localizableSampleTemplate(
  for complication: CLKComplication
) async -> CLKComplicationTemplate? {

}
  let start = Calendar.current.date(
    bySettingHour: 10, minute: 0, second: 0, of: .now
  )!
  let end = Calendar.current.date(
    byAdding: .hour, value: 1, to: start
  )!
  return CLKComplicationTemplateGraphicRectangularFullView(
    EventView(event: .init(
      color: .blue,
      startDate: start,
      endDate: end,
      title: "Gnomes rule!",
      location: "Everywhere"
    ))
  )

The current appointment

Just like when using non-SwiftUI templates, you have to provide the current timeline entry if one exists.

return timelineEntry(for: EventStore.shared.nextEvent)

Future appointments

It is likely you have more than one event on your calendar every day.

func timelineEntries(
  for complication: CLKComplication,
  after date: Date,
  limit: Int
) async -> [CLKComplicationTimelineEntry]? {

}
  guard let events = EventStore.shared.eventsForToday() else {
    return [timelineEntry(for: nil)]
  }
  let wanted = events
    .filter {
      date.compare($0.startDate) == .orderedAscending
    }
    .prefix(limit)
    .map { timelineEntry(for: $0) }
  return wanted.count > 0 ? wanted : [timelineEntry(for: nil)]
}

Tinting

In EventView.swift, just after the .foregroundColor(event.color) line of RoundedRectangle, add the complication foreground modifier

.complicationForeground()
.previewContext(faceColor: .green)