watchOS 10+ Frameworks

Setup watchOS 10+ for Advanced Development

Siamak (Ash) Ashrafi
15 min readFeb 27, 2024
WatchOS 10

We keep hearing people say “this or that will not work on watchOS”. In this article we show the entire Apple dev stack works on watchOS 10+.

Swift · SwiftUI · SF Symbols · SwiftData · Swift Charts · Swift Structured Concurrency · Swift Package Manager · XCTest · Watch Complications · HealthKit · Core Motion · Core ML & other modern frameworks.

Note: Please check the end of the article for functions / features that do not work on the watchOS 10+ simulator.

We already talked about the importance of smartwatches.

And overview of WearOS & iWatch development.

Modern Frameworks

We will build a watchOS project that includes all the modern frameworks.

Shared Tech Stack (iOS & watchOS)

iOS & watchOS: Swift · SwiftUI · SF Symbols · SwiftData · Swift Charts · Swift Structured Concurrency · Swift Package Manager · XCTest

Swift:

  • SwiftUI: Enables intuitive and visually appealing UI design, leveraging SF Symbols for consistent and platform-specific icons.
  • SwiftData: Simplifies local data storage and access, offering offline capabilities for your watch app.
  • Swift Charts: Powerful and concise SwiftUI framework for transforming your data into informative visualizations.
  • Swift Structured Concurrency (SSC): Handles asynchronous operations seamlessly with async/await, improving code readability and performance.
  • Swift Package Manager: Makes dependency management streamlined, keeping your project organized and up-to-date.

With:

  • HealthKit Integration: Access health data like heart rate, steps, and activity levels.
  • Watch Complications: Small data snippets displayed on watch faces, providing quick access to essential information.
  • Core ML: Integrate machine learning models into your app
  • Core Motion: Process accelerometer, gyroscope, pedometer, and environment-related events.

Note: We do NOT use MVVM with SwiftData*

  • SwiftData already abstracts data logic through its model management and querying capabilities. Implementing a separate MVVM structure will lead to overlap in data handling, inevitably causing problems.

Note: WatchKit Framework uses storyboards and Interface Builder. Apple advices AGAINST using it*.

Building the watchOS 10+ Project

Already included in XCode Version 15.3 beta 3:

Swift · SwiftUI · SF Symbols · SwiftData · Swift Charts · Swift Structured Concurrency · Swift Package Manager · XCTest & etc …

But we need to add HealthKit to our watchOS project:

HealthKit provides a central repository for health and fitness data on iPhone and Apple Watch. With the user’s permission, apps communicate with the HealthKit store to access and share this data. — Apple Docs

Adding HealthKit

Under the Signing & Capabilities click the plus button “+ Capability”

Click the plus button (+)

Add Capabilities in the upper left corner

Add HealthKit. Choose HealthKit.

Add HealthKit to our project

Now we have HealthKit in our project.

Add HealthKit Capabilities

WWDC workout app using HealthKit

Code Example ~~~

Make sure HealthKit is installed and working properly.

import SwiftUI
import HealthKitUI
import SwiftData


struct HealthInfoUIView: View {
var body: some View {
if HKHealthStore.isHealthDataAvailable() {
Text("Health Kit is Here")
} else {
Text("Healthkit is missing")
}
HealthAlertUI()
}
}

In the next project we will show how to access this data but for now we just want to make sure it works with watchOS 10+.

✅ This shows HealthKit is working on watchOS 10+.

SwiftData

SwiftData makes it easy to persist data using declarative code. You can query and filter data using regular Swift code. And it’s designed to integrate seamlessly with SwiftUI. — Apple Docs

Our article on SwiftData:

Code Example

Steps:

  1. Define your models in a Swift file.
import Foundation
import SwiftData

@Model
class HealthInfoModel {
var name: String = "Name"
init(name: String) {self.name = name}
}

@Model
class ToyShape {
var type: String
init(type: String) {self.type = type}
}

2. Add containers to your main <app name>App.swift

import SwiftUI

@main
struct HealthML_Watch_AppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: [HealthInfoModel.self, ToyShape.self])
}
}

Now we can use it by getting the modelContext and models

import SwiftUI
import SwiftData

struct HealthAlertUI: View {
@Environment(\.modelContext) var modelContext
@Query var healthMod: [HealthInfoModel]
@Query var toyShape: [ToyShape]

Add / Delete data is super easy!

// Add
modelContext.insert(HealthInfoModel(name: "This"))
modelContext.insert(ToyShape(type: "Cube"))

// Delete all
do {
try modelContext.delete(model: HealthInfoModel.self)
try modelContext.delete(model: ToyShape.self)
} catch {
fatalError(error.localizedDescription)
}

We can simply use the data in SwiftUI and it will auto update the UI without any extra work!

Text("Count is \(healthMod.count) & \(toyShape.count)")

✅ This also shows ✅ Swift / ✅ SwiftUI / ✅ Swift Structured Concurrency and ✅ SwiftData are working on watchOS 10+.

SF Symbols

watchOS 10+ has symbol effects!

The following example adds a bounce effect to two symbol images and “animates” mail, the animation will play each time counter changes.

import SwiftUI

struct RunManUIView: View {
@State private var isRunning = true
@State private var animationsRunning = true
@State private var counter = 0
@State private var isFavorite = false

@available(macOS 14.0, iOS 17.0, tvOS 17.0, watchOS 10.0, *)
var body: some View {
ScrollView {
Button("bounce", action: {
counter += 1
isFavorite.toggle()
})
HStack {
Image(systemName: "bolt.slash.fill")
Image(systemName: "folder.fill.badge.person.crop")
}
.symbolEffect(.bounce, value: counter)

VStack {
Image(systemName: "mail.stack")
}.symbolEffect(.bounce, options: .speed(3).repeat(3), value: isFavorite)
.font(.largeTitle)


}
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.white, lineWidth: 2)
)
}
}
SF Symbols working with symbolEffect

Running man (almost) made with only a few lines of SF Symbol and Swift Structured Concurrency (SCC).

struct SFImageToggle: View {
@State private var isSymbol1 = true
@State private var isRunning = false

let symbol1: String
let symbol2: String

var body: some View {
Image(systemName: isSymbol1 ? symbol1 : symbol2)
.font(.system(size: 120))
.symbolRenderingMode(.palette)
.foregroundStyle(.green, .gray)
.symbolEffect(.bounce.byLayer, options: .repeating, value: isRunning)
.symbolEffect(.variableColor, options: .repeating, value: isRunning)
.onAppear {
Task {
while true {
try await Task.sleep(nanoseconds: 700000000)
withAnimation {
self.isSymbol1.toggle()
}
}
}
isRunning.toggle()
}
}
}

Every SF Symbol. Find what you are looking for in a few min.

✅ SF Symbols with animation and SCC works on watchOS 10+.

Swift Charts

Swift Charts is a declarative framework by Apple for creating beautiful and interactive charts in SwiftUI applications. It offers a convenient and efficient way to visualize data through various chart types.

Key Features:

  • Declarative Syntax: Instead of writing low-level drawing code, you describe the chart’s structure and desired behavior using Swift code, making it easier to read and maintain.
  • Rich Chart Types: It supports a range of common chart types, including bar charts, line charts, pie charts, scatters plots, histograms, and more.
  • Customization: You can customize various aspects of the chart, such as colors, fonts, labels, axes, legend, and animations, to match your app’s design and data.
  • Integration with SwiftUI: Swift Charts seamlessly integrates with SwiftUI, allowing seamless placement of charts within views and leveraging SwiftUI’s features like modifiers and bindings.

Benefits:

  • Improved Readability: Declarative syntax makes your code more readable and easier to maintain.
  • Reduced Development Time: Building charts becomes faster and more efficient compared to manual drawing or using third-party libraries.
  • Better User Experience: Interactive and visually appealing charts enhance user engagement and understanding of data.

Getting Started:

  1. Import the framework: Add import Charts to your SwiftUI file.
  2. Define your data: Prepare your data in a suitable format, such as arrays or structs.
  3. Create the chart view: Use the Chart view and its modifiers to define the chart type, data, and desired customizations.

Code Example ~~~

Get our data from SwiftData and show it using Swift Chats on watchOS 10+

struct HealthChatUIView: View {
@Environment(\.modelContext) var modelContext
@Query var toyShape: [ToyShape]
@Query var hInfoMod: [HealthInfoModel]

var body: some View {
VStack {
Text("Switf Charts & SwiftData")
Chart {
BarMark(
x: .value("Shape Type", "toyShape"),
y: .value("Total Count", toyShape.count)
)
BarMark(
x: .value("Health", "Health"),
y: .value("Total Count", hInfoMod.count)
)
}
}
}
}

The chats are bound to the data and update in real-time as the data changes just like any SwiftUI view connected to SwiftData.

✅ Swift Chats connected to SwiftData works on watchOS 10+.

Core Motion

Process accelerometer, gyroscope, pedometer, and environment-related events.

Code Example ~~~

import SwiftUI
import CoreMotion

struct ContentView: View {
@State private var accelerationData = "No data yet"
let motionManager = CMMotionManager()

var body: some View {
Text(accelerationData)
.padding()
.onAppear {
startAccelerometerUpdates()
}
}

func startAccelerometerUpdates() {
if motionManager.isAccelerometerAvailable {
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdates(to: .main) { data, error in
guard let acceleration = data?.acceleration else {
self.accelerationData = "Error: \(error?.localizedDescription ?? "Unknown error")"
return
}
self.accelerationData = "X: \(acceleration.x), Y: \(acceleration.y), Z: \(acceleration.z)"
}
} else {
self.accelerationData = "Accelerometer not available"
}
}
}

✅ Core Motion works on watchOS 10+.

Core ML

Apple’s Machine Learning offers tools and resources to help developers:

  • Embed intelligence: Add features like image recognition, natural language processing, and more to their apps.
  • Use pre-trained models: Leverage pre-built models like Core ML and Create ML for common tasks without extensive training.
  • Train custom models: Create their own custom models with tools like Create ML and train them using data specific to their app.

This page caters to developers seeking to integrate machine learning capabilities into their iOS, iPadOS, macOS, and watchOS apps.

We need to generate a ML model.

Experience an entirely new way of training machine learning models on your Mac. Create ML takes the complexity out of model training while producing powerful Core ML models.

Or download one from Apple.

We will use the MNIST ML model.

Get the MNIST ML model from Apple.

Add this to XCode.

Add the model to your Xcode project by dragging the model into the project navigator.

Add ML model to App

Overview of the model in XCode

Running “MNIST” on the watchOS 10+

func classifyImage() {
guard let model = try? MNISTClassifier(configuration: MLModelConfiguration()) else {
print("Failed to load model")
return
}

// Convert drawn image to UIImage
let image = UIImage(view: DrawingView(path: path))

// Convert the image to a format suitable for the model
guard let pixelBuffer = image?.pixelBuffer(width: 28, height: 28) else {
print("Failed to convert image to pixel buffer")
return
}

// Perform classification
do {
let prediction = try model.prediction(image: pixelBuffer)
predictedDigit = prediction.classLabel
} catch {
print("Error making prediction: \(error)")
predictedDigit = "Error"
}
}

We have an entire article on how to do this …

✅ Core ML works on watchOS 10+.

Core Image

Core image does not work on watchOS (never / no versions)

⛔️ Core Image does NOT work on watchOS (never has).

SwiftUI — for watchOS 10+

Although we know SwiftUI runs on watchOS 10+ it is different than iOS.

watchOS 10 provides a redesigned user interface that focuses on relevant, glanceable content and consistent navigation, and takes advantage of the high-quality display with full-screen color and images.

When designing your app, use these features to create efficient, intuitive navigation:

  • TabView provides a set of views that people can scroll through using the Digital Crown.
  • NavigationSplitView toggles between a source list and a set of detail views.
  • NavigationStack moves into and back out of a hierarchy of views.

Use these features to make your app consistent and visually coherent:

SwiftUI is slightly different on watchOS 10+

Available UI Elements:

  • iOS: Offers a wider range of UI elements like text fields, sliders, pickers, and more.
  • watchOS: Has a limited set of UI elements due to the smaller screen and focus on user interaction with the Digital Crown and buttons. It focuses on providing essential elements like buttons, labels, images, and basic navigation.

Layout Adaptivity:

  • iOS: Supports various screen sizes and orientations, requiring more consideration for adaptive layouts.
  • watchOS: Has a single screen size and orientation, simplifying layout design and requiring less adaptive code.

Interactions and Input:

  • iOS: Primarily relies on touch gestures and text input for interaction.
  • watchOS: Leverages the Digital Crown for scrolling, selection, and other interactions alongside taps and buttons. Due to the smaller screen, text input can be challenging and might require alternative methods like dictation.

Notifications and Complications:

  • iOS: Primarily focuses on in-app experiences.
  • watchOS: Has dedicated APIs for building interactive notifications and complications (mini apps displayed on the watch face).

Architectural Considerations:

  • iOS: Apps can have multiple views and complex hierarchies.
  • watchOS: Encourages simpler app structures with fewer views due to the limited screen size and focus on single-handed interaction.

App Lifecycle:

  • iOS: Apps often run in the background and can enter background states.
  • watchOS: Apps typically run in the foreground and have stricter constraints on background activity due to battery limitations.

SwiftData Support:

  • iOS: Can use SwiftData framework for data persistence and management.
  • watchOS: SwiftData might have limitations in watchOS due to storage and iCloud access.

In summary:

  • SwiftUI’s core syntax and principles remain the same, but the available features and considerations differ based on the unique characteristics of each platform.
  • Adapting your SwiftUI code to work on both platforms requires careful consideration of these differences and platform-specific best practices.

The Apple Human Interface Guidelines for watchOS

Comprehensive guidance for designing apps specifically tailored for the Apple Watch. Here’s a summary of the key points covered in the document:

Design Principles

  • Simplicity and Efficiency: Prioritize essential information and actions, making interactions quick and easy.
  • Clarity: Ensure content is clear and easy to understand, using legible text and simple graphics.
  • Vitality: Create engaging experiences with animations and transitions that provide feedback and delight users.

Navigation

  • Hierarchical Structure: Design apps with a clear hierarchical structure to organize content and simplify navigation.
  • Modal Sheets: Use modal sheets for presenting transient information or actions, ensuring they can be dismissed easily.

UI Elements

  • Buttons: Make buttons large and tappable, avoiding crowded layouts.
  • Labels: Use concise and clear labels to convey information effectively.
  • Images: Utilize images to enhance visual appeal and provide context.
  • Tables and Lists: Display information in tables or lists for easy scanning and interaction.

Interaction

  • Taps and Force Touch: Use taps and force touch gestures for primary interactions, providing additional functionality through force touch.
  • Digital Crown: Leverage the Digital Crown for scrolling, zooming, and precise adjustments, enhancing user control.
  • Voice Commands: Integrate Siri for voice interactions, allowing users to perform tasks hands-free.

Complications

  • Glanceable Information: Design complications to provide glanceable information directly on the watch face, helping users stay informed at a glance.
  • Personalization: Allow users to customize complications to display the information most relevant to them.

Notifications

  • Timely and Relevant: Deliver notifications that are timely, concise, and provide clear actions.
  • Interactive Notifications: Enable interactive notifications to allow users to take action directly from the notification interface.

Accessibility

  • VoiceOver: Ensure apps are accessible to users with visual impairments by providing support for VoiceOver.
  • Readable Text: Use legible fonts and appropriate text sizes to ensure readability.

Localization

  • Cultural Sensitivity: Consider cultural differences when designing interfaces and content, ensuring inclusivity and sensitivity to diverse audiences.

Performance

  • Optimization: Optimize app performance to provide a smooth and responsive user experience, minimizing loading times and maximizing efficiency.

Testing and Feedback

  • User Testing: Conduct thorough user testing to gather feedback and iterate on designs, ensuring usability and effectiveness.
  • Beta Testing: Utilize beta testing to gather feedback from a wider audience and identify potential issues before release.

Overall, designing for watchOS requires a focus on simplicity, clarity, and efficient interactions to create intuitive and engaging experiences tailored to the unique characteristics of the Apple Watch.

Summery

1. Design for Simplicity and Efficiency:

  • Focus on essential information and actions: Prioritize readily available and easily accessible information relevant to the user’s context.
  • Prioritize tap and Digital Crown interactions: Design for efficient use of the limited screen size and focus on touch and Digital Crown interactions.
  • Simplify information hierarchy: Present information in a clear and concise manner, avoiding overwhelming users with complex details.

2. Leverage Watch Complications:

  • Provide actionable information at a glance: Utilize watch complications (mini-apps displayed on the watch face) to offer relevant, dynamic information for immediate access.
  • Design for quick updates and interactions: Ensure complications update promptly and allow users to readily perform actions within them.

3. Emphasize Personalization and Timeliness:

  • Anticipate user needs: Leverage on-device data and user patterns to proactively surface relevant information and actions.
  • Tailor notifications for immediacy: Deliver notifications that are concise, timely, and provide clear action options.
  • Embrace dynamic content: Utilize background colors and materials strategically to convey contextual information and enhance user engagement.

4. Prioritize Accessibility and Inclusivity:

  • Follow accessibility guidelines: Ensure your app is accessible to users with diverse abilities by adhering to Apple’s accessibility guidelines.
  • Support VoiceOver: Enable VoiceOver screen reader functionality to guide users through the app’s interface using voice instructions.

5. Adhere to Apple’s Design Language:

  • Maintain consistency with Apple’s design language: Ensure your app aligns with Apple’s established visual style and user interface elements for a familiar and seamless experience.
  • Utilize provided resources: Refer to Apple’s Human Interface Guidelines and sample code to guide your design decisions and implementation.

Overall, emphasizes creating watchOS experiences that are:

  • Simple and efficient: Facilitate quick access to information and actions.
  • Contextually relevant: Provide timely and personalized information based on user needs and context.
  • Visually appealing and accessible: Follow Apple’s design language and accessibility guidelines.

By following these key principles and leveraging the watchOS-specific features, you can design effective and delightful user experiences for your Apple Watch app.

Not Working On watchOS Simulator (XCode)

The watchOS simulator has limitations and cannot fully replicate the experience of using a physical Apple Watch. Here’s a list of functionalities that are not supported by the simulator:

Hardware-based features:

Simulator doesn’t support the following hardware:

  • Ambient light sensor
  • Audio input, except for using Siri by choosing Device > Siri
  • Barometer
  • Bluetooth
  • Camera
  • Motion support (accelerometer and gyroscope)
  • Proximity sensor

Sensors:

  • Accelerometer / Gyroscope
  • Heart Rate sensor
  • Blood Oxygen sensor (on Apple Watch Series 6 and later)
  • Other sensors present on newer watch models

Communication features:

  • Cellular connectivity (if applicable), Walkie-Talkie, Emergency SOS

Physical interactions:

  • Touch detection beyond basic taps and swipes

Simulator doesn’t support the following frameworks:

The following features of APIs are not available in Simulator:

  • Receiving and sending Apple push notifications. Drag and drop a JSON file with a push notification payload on the simulator to test receiving a push notification.
  • The UIBackgroundModes key.

Additionally:

  • GPS: While the simulator can simulate location data to some extent, it cannot replicate the real-time location tracking capabilities of a physical device.
  • Background App Refresh: The simulator might not fully simulate how background app refresh works on a physical device.

We hope this article helps clarify watchOS 10+ development.

~Ash

--

--