watchOS

Overview

This post explains the steps for creating a watchOS app that runs on an Apple Watch. It also shows how to create and run paired iOS and watchOS apps that can send messages between each other.

Apple guidelines on watchOS development can be found here. This begins with "Apple Watch provides easy access to vital information on someone’s wrist. The watchOS experience focuses on quick actions that achieve useful tasks through brief, punctuated interactions."

watchOS supports a subset of SwiftUI. I have not been able to find documentation that identifies that subset. If an app attempts to use a SwiftUI feature in a watchOS app that is not supported, a compile-time error will be displayed.

watchOS apps can be independent of any iOS app or they can have a companion iOS app. When there is a companion app, they can share data by using the WatchConnectivity framework to send messages.

Project Creation

Example Code

The following code implements a countdown timer app.

WatchOS Timer App #1 WatchOS Timer App #2 WatchOS Timer App #3

import SwiftUI

struct ContentView: View {
@State var isTimerPresented = false
@State var timerValue = 5

var body: some View {
VStack {
Text("Timer").font(.system(size: 40))
Picker(selection: $timerValue, label: Text("")) {
Text("5").tag(5)
Text("10").tag(10)
Text("15").tag(15)
Text("30").tag(30)
}
NavigationLink(
destination: TimerView(
isPresented: $isTimerPresented,
timerValue: timerValue
),
isActive: $isTimerPresented,
label: { Text("Start") }
)
.foregroundColor(.green)
}
}
}

struct TimerView: View {
@Binding var isPresented: Bool
@State var timerValue: Int

func startTimer() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
if timerValue > 0 {
timerValue -= 1
} else {
timer.invalidate()
}
}
}

var body: some View {
VStack {
if timerValue > 0 {
Text("Time remaining")
.onAppear() { startTimer() }
Text("\(timerValue)").font(.system(size: 40))
Text("seconds")
Button("Cancel") { isPresented = false }
.foregroundColor(.red)
} else {
Button("Done") { isPresented = false }
}
}
}
}

eleventyNavigation: key: Apple Watch (watchOS) parent: Swift order: 4 layout: topic-layout.njk


Simulator vs. Devices

Running on the Simulator is fairly fast and is preferred for most testing.

To deploy a watchOS app to an Apple Watch:

App Icons

To add app icons to a watchOS app:

Launch Screen

watchOS apps do not currently support launch screens. When an app launches, it's icon is displayed inside an indeterminate, circular status bar. See https://stackoverflow.com/questions/69113082/how-can-we-add-a-launch-screen-to-a-watch-app.

Launching from a Complication

To create a watch face complication that launches a custom app when tapped:

  1. Open the "Watch" app on the iPhone that is paired with the watch.
  2. Tap the "My Watch" tab on the bottom navigation.
  3. Select a watch face that supports complications.
  4. Scroll down to the "Complications" section.
  5. Tap a complication.
  6. Scroll to the custom app and tap it.

The app icon should appear as the complication icon, but all I see so far is two dashes in its place. Perhaps this happens because the app was not downloaded from the store or perhaps it is a watchOS bug.

Display Name

To change the display name of a watchOS app:

  1. Select the top entry in the Navigator.
  2. Under TARGETS, select the target whose name ends in " App".
  3. Change the value of "Display Name".
  4. Deploy the app again.

iOS and watchOS App Pair

To create an app that runs on both an iPhone and Apple Watch (companion apps):

  1. In Xcode, select File ... New ... Project...
  2. Select the "watchOS" tab.
  3. Select "App".
  4. Click the "Next" button.
  5. Enter a project name.
  6. Select the "Watch App with New Companion iOS App" radio button.
  7. Click the "Next" button.
  8. Select the directory where the project will be saved.
  9. Click the "Create" button.

The iOS app is defined by files in the "{project-name}" directory. The watchOS app is defined by files in the "{project-name} WatchKit Extension" directory.

To share data between these apps, use the WatchConnectivity framework. See https://www.youtube.com/watch?v=i3_6m0a5ovw.

  1. Select the top item in the Navigator.
  2. Under "TARGETS", select the first target.
  3. Select the "General" tab.
  4. In the "Frameworks, Libraries, and Embedded Content" section, click the "+" button, select "WatchConnectivity.framework", and click the "Add" button.

To make some of the iOS source files also available to watchOS:

  1. Click the top item in the Navigator.
  2. Under "TARGETS", select the target whose name ends with " WatchKit Extension".
  3. Click the "Build Phases" tab.
  4. Open the "Compile Sources" section.
  5. Click the "+" at the bottom of the section.
  6. Select the files Data.swift, ConnectionProvider.swift, and ViewModel.swift.
  7. Click the "Add" button.

To create a pair of simulators (one iPhone and one Apple Watch) that can be launched together:

  1. Click the device dropdown at the top of Xcode.

  2. Select "Add Additional Simulators..." which opens a dialog.

  3. Enter a name such as "iPhone 14 Pro + Apple Watch 7".

  4. Select the phone device type such as "iPhone 14 Pro".

  5. Check the "Paired Apple Watch" checkbox.

  6. Click the "Next" button.

  7. Select a Watch model from the "Device Type" dropdown.

  8. Click the "+" at the bottom of the left nav.

  9. Select an iPhone model from the "Device Type" dropdown such as "Apple Watch Series 7 (45mm)".

  10. Select an OS version from the "OS Version" dropdown such as "watchOS 9.0".

  11. Click the "Create" button.

  12. The new simulator should appear in the list on the left of the dialog.

  13. Close the dialog.

  14. Select the newly created simulator pair name from the device dropdown.

To run both the iPhone and Apple Watch apps in the Simulator:

  1. Select the Simulator created above from the device dropdown at the top.
  2. Press the play button (triangle) to run the iOS app in the Simulator.
  3. Click the dropdown at the top that is displaying the current app name.
  4. Select the entry that begins with the app name and ends with " WatchKit App".
  5. Press the play button (triangle) again to run the watchOS app in the Simulator.
  6. The debug console at the bottom will show the output from one of the apps. To see output from the other app, select it from the app name dropdown at the top of the debug console.

To run on real devices, enable developer mode on both the phone and watch. On the phone, ADD THIS DETAIL. On the watch, launch the Settings app and select Privacy & Security ... Developer Mode and toggle it on.

For an example app, see watch-with-ios-2 in GitHub.