Adding Complications to Your watchOS App Using SwiftUI

Amit Srivastava
3 min readAug 29, 2023

--

The term “complication” in the world of watchOS refers to any feature on a watch face that displays more than hours and minutes. In the Apple Watch ecosystem, complications give quick access to information and features provided by apps. With the introduction of SwiftUI for watchOS, building complications has become more straightforward.

In this article, we’ll walk through the process of adding complications to your watchOS app using SwiftUI.

1. Setting up your project

Begin by creating a new SwiftUI-based watchOS app using Xcode. When setting up your project, ensure you check “Include Complication” to have the necessary template files generated for you.

2. Understanding Complication Families

Apple Watch supports multiple watch faces, each with space for various complications. These spaces, defined by design, are called complication families. Some common families are:

  • Modular Small
  • Modular Large
  • Utilitarian Small
  • Utilitarian Large
  • Circular Small

It’s important to design for each family to ensure a seamless user experience.

3. Building the Complication View

With SwiftUI, you can design the complication’s view just like any other view. Here’s an example of a simple complication view:

struct ComplicationView: View {
var body: some View {
VStack {
Image(systemName: "bell.fill")
Text("6 Alerts")
}
}
}

4. Integrating with CLKComplicationTemplate

To bridge your SwiftUI view with the complication system, wrap it inside a CLKComplicationTemplate.

For instance, for a Modular Small complication:

func createTemplate() -> CLKComplicationTemplate {
let provider = CLKTextProvider(format: "6 Alerts")
let template = CLKComplicationTemplateModularSmallSimpleText(textProvider: provider)
return template
}

5. Providing Data

ComplicationController.swift is the primary file to manage and provide data for your complications. You'll find several methods, such as getCurrentTimelineEntry, getTimelineStartDate, etc., which determine how and when your complications fetch and display data.

Here’s a simple implementation to provide current data:

func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
// Fetch your data (maybe from UserDefaults, Core Data, or an API)
let template = createTemplate()
let entry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
handler(entry)
}

6. Configuring the Info.plist

Once your complication controller is set up, you need to tell watchOS about it. This is done via the Info.plist file of your WatchKit Extension.

  1. Open Info.plist in your WatchKit Extension.
  2. Locate the WKCompanionAppBundleIdentifier key and ensure it points to your iOS app's bundle identifier.
  3. Next, you’ll need to add a new key: CLKComplicationPrincipalClass. Set its value to the name of your complication controller class, which should be something like $(PRODUCT_MODULE_NAME).ComplicationController.

This step ensures that the watchOS knows which class to communicate with when updating or fetching data for your complication.

7. Handling User Taps

When users tap on your complication, you would often want to take them to a specific view in your app. Handle this within the handleSharedComplicationDescriptors function in the Extension Delegate:

func handle(_ complicationDescriptors: [CLKComplicationDescriptor]) {
// Navigate the user to a specific view
}

8. Testing Your Complication

With the WatchKit simulator, you can easily test your complications. To ensure all possible scenarios are covered:

  • Test on various watch faces.
  • Check different data points to ensure your complication adjusts correctly.
  • Ensure the complication is tappable and leads to the desired view.

9. Tips for a Great Complication

  • Keep it Simple: Complications are meant to provide quick information. Avoid overloading them.
  • Update Regularly: Ensure your complication updates when new data becomes available.
  • Adaptability: Ensure your complication looks good in all watch faces and sizes.

Conclusion

Incorporating complications in your watchOS apps provides users with quick and accessible information. Adding these to the Info.plist ensures a seamless integration of your code with the watchOS complication system. With SwiftUI streamlining the development process, you can now more easily harness the power of complications to enhance your app's user experience on the Apple Watch.Hope this helps in your watchOS development journey.

--

--