Hide chapters

watchOS With SwiftUI by Tutorials

First Edition · watchOS 8 · Swift 5.5 · Xcode 13.1

Section I: watchOS With SwiftUI

Section 1: 16 chapters
Show chapters Hide chapters

13. Face Sharing
Written by Scott Grosch

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

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

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

Unlock now

While the ability to create and use complications has existed for years, being able to share the perfect watch face with your friends and customers is a new feature. Most apps you develop will only have a single complication. Sometimes, however, you might provide multiple complications.

Consider the TideWatch app you built in previous chapters. Currently, there’s a single complication that displays the tide. You might wish to extend the app to include complications that provide the current water temperature and wind conditions. When it makes sense to group multiple complications from your app or other apps, you can now offer a way for your customers to receive a preconfigured watch face easily.

Note: You’ll need a physical device to send a watch face from the iPhone to the Apple Watch.

Sharing faces

There are four ways you can share a watch face:

  1. Using the Watch app on your iOS device.
  2. Directly from your watch.
  3. Downloading a watchface file from the web.
  4. Adding it via your custom iOS app.

From the iPhone

One of the simplest ways to share a watch face is by running the Watch app on your iPhone. When the app opens, you’ll see all of the watch faces you have currently configured:

From the Apple Watch

It’s even easier to share from the Apple Watch. From the home screen, long-press the watch face and choose the share icon. Then select to whom you’d like to send the watch face:

From the web

If you want to share multiple watch faces, you may wish to host them on your app’s website. Point your favorite browser to Apple’s Human Interface Guide (HIG). Scroll down to the Technologies section, and you’ll see a download available for Add Apple Watch Face. Download the file, which is a DMG, and then double-click it. You’ll see a window containing the developer license as well as an Assets folder.

<link rel="stylesheet" href="style.css">
<h1>My Cool App</h1>
<p>We really think you'll love this watch face!</p>

<hr />
  <img src="preview.png">

  <a href="FaceToShare.watchface"
    <img src="download.svg">

    You can scan the below QR code to install the watch face from your
    paired iOS device.
  <img alt="QR Code" class="qrcode" src="qrcode.png">

From the iOS app

You have one final option for providing a preconfigured watch face. You can embed the face right into your iOS app. The advantage of this approach is that the person using your app doesn’t have to transition to a website. You simply provide them some mechanism to send the face directly to the paired Apple Watch via one of the HIG buttons you downloaded.

Setting up the session

In the Watch Connectivity chapter, you learned about WCSession and WCSessionDelegate. To know whether an Apple Watch is paired to the iOS device, you’ll need the same type of session running. If there’s not a paired Apple Watch, then you wouldn’t want to provide the option to install a custom watch face.

// 1
var showFaceSharing = false

private func updateFaceSharing(_ session: WCSession) {
  // 2
  let activated = session.activationState == .activated
  let paired = session.isPaired

  // 3
  DispatchQueue.main.async {
    self.showFaceSharing = activated && paired
func sessionWatchStateDidChange(_ session: WCSession) {

Showing the share button

Now open ContentView.swift. Currently, you only show an image of the face which you’ll send to the watch. You need to include a download button, but only if there’s a paired Apple Watch.

// 1
if session.showFaceSharing {
} else {
  // 2
  Text("Unable to share watch face")
  // 3
  Text("Please pair an Apple Watch first")
// 1
func sendWatchFace() async {
  // 2
  guard let url = Bundle.main.url(
    forResource: "FaceToShare",
    withExtension: "watchface"
  ) else {
    // 3
    fatalError("You didn't include the watchface file in the bundle.")
import ClockKit
// 1
let library = CLKWatchFaceLibrary()

// 2
do {
  // 3
  try await library.addWatchFace(at: url)
} catch {
  // 4
Button {
  Task { await sendWatchFace() }
} label: {

Handling shared complications

When the Apple Watch receives a shared complication, ClockKit will call handleSharedComplicationDescriptors(_:) on your watchOS extension’s CLKComplicationDataSource. Depending on how your app structured its complications, you may or may not need to implement that delegate method.

func handleSharedComplicationDescriptors(
  _ complicationDescriptors: [CLKComplicationDescriptor]
) {
  for descriptor in complicationDescriptors {
      let userInfo = descriptor.userInfo,
      let type = userInfo[truckTypeKey] as? String
    else {

    // Add the new truck type

Key points

  • Only install a watch face if the user requests it.
  • Don’t offer to install a watch face if there is no paired device.
  • Anyone can create shareable watch faces, but only you can offer them from inside the app.
  • Remember to handle complication-specific data.

Where to go from here?

  • The sample materials for this chapter contain a web folder that includes the full source to the sample webpage.
  • Check out the amazing Watchfacely site for great examples of sharing faces via the web.
  • Many sites on the web will generate QR codes for free, such as QR Code Generator.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now