Streaming is available in most browsers,
and in the WWDC app.
-
Build complications in SwiftUI
Spice up your graphic complications on Apple Watch using SwiftUI. We'll teach you how to use custom SwiftUI views in complications on watch faces like Meridian and Infograph, look at some best practices when creating your complications, and show you how to preview your work in Xcode 12. To get the most out of this session, you should be familiar with the basics of SwiftUI and building complications on Apple Watch. For an overview, watch “Create Complications for Apple Watch” and read “Building watchOS App Interfaces with SwiftUI.” Once you've discovered how to build graphic complications in SwiftUI, you can combine this with other watchOS 7 features like multiple complications and Face Sharing to create a watch face packed with personality and customized for people who love your app.
Resources
- Building a watchOS App
- ClockKit
- Creating and Updating a Complication’s Timeline.
- Have a question? Ask with tag wwdc20-10048
- Search the forums for tag wwdc20-10048
Related Videos
WWDC 2021
WWDC 2020
-
Download
Hello and welcome to WWDC.
Hi, my name is Matthew Koonce and I'm a watchOS SwiftUI engineer.
I'll be joined later by my colleague, August. Today we get to dive into all the awesome things you can build with SwiftUI complications. Complications are how you display timely and relevant information about your app on the watch face. Some of the most powerful and useful complications are able to distill complex information into something that can be quickly understood at a glance. For example, the UVI complication features vertical gauges with a color gradient which quickly tells me that sunscreen would be a good choice today.
Building complications like the UVI chart can be challenging. But with SwiftUI complications, you can bring your knowledge about SwiftUI right to the watch face. And of course, we can't have SwiftUI complications without Xcode previews. Now you can view your complications on different faces at the same time.
So today we're going to take a look at how you can build your own complication in SwiftUI. To do that, we'll look at the new API in ClockKit and SwiftUI that make this all possible.
We'll see how our SwiftUI views work with watch face tinting and some best practices. Let's get started with the API.
In order to use SwiftUI views in complications, we turn to our trusty complication templates. ClockKit has dozens of predefined templates that provide easy-to-use layouts for your complications.
New in watchOS 7, we've added templates that take a SwiftUI view right alongside other ClockKit providers. These templates are for the Graphic Corner, Circular, Rectangular...
and Extra Large families. But where SwiftUI really shines are the templates that take just a single SwiftUI view. These templates provide a full canvas for drawing in each family.
And the GraphicRectangularFullView template is a brand-new template that gives you an even larger canvas for drawing.
And with that canvas, you can use SwiftUI to do just about anything. SwiftUI's powerful drawing library is at your full disposal, allowing you to easily create novel designs for complications like this awesome tide chart from Dawn Patrol. So that's how you can get your SwiftUI views into ClockKit templates. We've also made changes in SwiftUI that bring more power and flexibility to complications.
First, let's talk about text. We've updated text to be aware of the complication family it will appear on. The default font size will change for each family. For example, this same text shown here in the GraphicRectangular complication will be much larger on the Extra Large face. The default font has also changed to SF Rounded to look right at home on the face.
Additionally, text features new date formatters that work great on the watch face. In particular, the relative, offset and timer styles will be automatically kept up-to-date by the watch face.
For example, using the relative style for this date will make sure it's always accurate relative to now.
Same for the timer style. I can place the date right inside an interpolated string and it will automatically show the time remaining on my Sourdough Timer.
So that's the improvements we've made to text. Next, let's look at two popular controls from complications that we've brought right into SwiftUI. Those are Progress View and Gauge.
Both Progress View and Gauge are super useful, and each have a specific purpose.
Progress View is great for information that progresses in a linear fashion, like music. And the Gauge is great for information that varies over time, like temperature. Let's start with Progress View.
In its most simple setup, Progress View just has a single value and can be set with a style.
In this case, we're using the Circular style.
We can also add a label to the Progress View which describes its purpose. In our case, we're using the music note SF symbol.
Finally, Progress Views can be tinted, completing the look of our musical Progress View.
Progress View also comes in a linear style. And all the same API works just like you'd expect. Next, let's look at Gauge.
Gauge is a superpowerful control with a ton of configuration options. Let's take a look.
Here we have a simple Gauge that shows the soil acidity level of our garden. It's using the CircularGaugeStyle.
We can also add a current value label that will appear in the center of the Gauge to provide some context at a glance.
For some Gauges, it might be useful to label the start and end values. In our case, our Gauge is from three to ten. So let's add those labels with the minimum and maximum value labels.
Like Progress View, Gauge can also be tinted with a color. Here we add a green color.
But where Gauges really come into their own is with a gradient tint. By using SwiftUI's gradient, I can easily specify the color stops for my acidity Gauge.
Gauge also comes in a linear style which is great for Rectangular complications like on the Modular Compact face.
So that's the Gauge API. But one thing to remember is that both Gauge and Progress Views are available in SwiftUI as a new control that you can build as needed. For example, we can use a Circular Gauge in a Rectangular complication...
or use Gauges right in the app.
So that's the new API we've added to SwiftUI and ClockKit. Next, let's talk about one of my favorite features of watch faces, watch face tinting.
Watch faces support a full range of tinted colors, allowing for even more personalization. Complications take on this face color, giving each face a unique style.
Some faces, like the Solar Dial face, take this a step further and alters the tint color and the color of each complication as the day progresses.
So understanding how your complication will behave on a tinted watch face is intrinsic to the design of your complication. So let's dive into how watch face tinting works.
I have a full color view here of a yellow apple over a blue circle. When the watch face becomes tinted by a color, one of two possible tinting effects will be applied.
The first is a desaturated tint. And the second is a color opacity tint.
Let's start by talking about desaturated tinting.
Desaturated tinting is the default tinting mode for complications. When the watch face is tinted, it creates a grayscale version of your view.
Some faces, like the Extra Large face, may apply a single color over this desaturated view. Let's see how we can build a SwiftUI complication that becomes desaturated on the watch face.
Here I have the code for my view which is a ZStack of a circle and an apple image.
On the watch face that looks pretty good.
When the watch face color is changed to red... you can see that the default desaturation mode kicks in, and the view becomes desaturated automatically on the watch face.
And on the Extra Large face, a single color is applied over the desaturated view. So that's pretty easy. With no changes to our SwiftUI view, we get a good tinted complication.
With that said, be mindful about the colors you choose for your complication.
If I had instead chosen colors with a similar brightness, the apple will just disappear when the view is desaturated. So it's important to consider how your view will look desaturated when building a complication.
So that's desaturated tinting. Next, let's look at color opacity tinting. While desaturated tinting is the default tinting behavior, color opacity is an alternative tinting style that we can opt into.
This tinting style works by creating layers within our complication. And then the watch face applies a color to each layer.
Starting with our fullColor view, we first want to identify the layers of our complication. Watch faces support two distinct layers.
In this case, we've chosen the circle to be separated from the apple. These will now be our two layers. Next, as the name implies, the watch face only considers the opacity of each view.
Since each of these views are at full opacity, they both become white.
Then the watch face applies a color to the appropriate layer. Each watch face determines the color applied to each layer. In this case, the watch face determined that the circle's layer should become red and the apple's layer should remain white.
Then the layers are brought back together.
It's up to the watch face to define how the chosen color is applied to each layer. On the Extra Large face, for example, our apple is white on a red background...
but will be red on a white background on the Meridian face.
And other faces, like the Solar Dial face, may apply a different color to both layers.

