watchOS: Apple Watch development basics with SwiftUI

Author: IT Sectr Published: 2026-02-07 Reading time: 12 min

watchOS is Apple's operating system for Apple Watch, first released in 2015 alongside the first watches. watchOS app development is done in Swift using SwiftUI and WatchKit. Key features: a small rectangular screen, limited battery consumption of 0.3 Wh, and tight integration with iPhone via Bluetooth. According to Counterpoint Research, Apple Watch holds over 30% of the global smartwatch market.

Key Takeaways

  • watchOS — OS for Apple Watch built on the XNU kernel with a focus on low power consumption
  • SwiftUI — the primary framework for developing watchOS app interfaces
  • Watch Connectivity — data exchange mechanism between Apple Watch and iPhone
  • Smart Stack — an intelligent widget stack introduced in watchOS 10
  • HealthKit — framework for accessing sensors: heart rate, SpO2, temperature, accelerometer

What is watchOS?

watchOS is the operating system for Apple smartwatches, based on the Darwin XNU kernel. First released on April 24, 2015, alongside the Apple Watch Series 0. The system is built on the same architecture as iOS but optimized for a small display (1.5 to 1.9 inches), limited memory (up to 1 GB RAM in Series 9), and minimal power consumption.

According to StatCounter (2026), watchOS holds approximately 55% of the smartwatch operating system market, ahead of Wear OS and proprietary systems from Chinese manufacturers. Apple releases major watchOS updates annually, supporting watches for up to 5 years from release.

A key feature of watchOS is its dependence on iPhone. Most apps use Watch Connectivity for data synchronization. Starting with watchOS 6, watches can install apps directly from the App Store, but full independence from iPhone is only supported with watchOS 9.

watchOS version history

The first version, Watch OS 1.0, did not support third-party apps — only pre-installed Apple apps. watchOS 2 (2015) opened the SDK for developers. watchOS 3 (2016) accelerated app launch by 7 times. watchOS 6 (2019) introduced the App Store on watches. watchOS 9 (2022) added medications and improved sleep tracking. watchOS 10 (2023) became the biggest interface update since release.

watchOS VersionYearKey Innovation
Watch OS 12015First version, only native Apple apps
watchOS 22015Open SDK, third-party apps, Watch Connectivity
watchOS 32016Instant app launch, Dock, Scribble
watchOS 62019App Store on watch, Cycle Tracking, Noise app
watchOS 92022Medications, sleep stages, improved running companion
watchOS 102023Smart Stack, Double Tap, new watch faces

watchOS Architecture

The watchOS architecture consists of three layers, isolating hardware from user applications. Unlike iOS, watchOS uses a component-based approach: an app consists of two targets — an extension and an iPhone host.

Kernel and system services

The bottom layer is a modified XNU kernel with drivers for Apple's S4/S5/S6/S7/S8/S9 chips. The Apple Watch Series 9 uses the S9 SiP with 5.6 billion transistors and a 4-core Neural Engine. System services include Core Bluetooth, Watch Connectivity, HealthKit, and Core Motion. All background tasks are managed through BGTaskScheduler — a system scheduler that optimizes power consumption.

WatchKit — application layer

WatchKit is a framework for creating watchOS app interfaces. It includes WKInterfaceController, WKInterfaceGroup, WKInterfaceLabel, and WKInterfaceButton. Since watchOS 6, Apple recommends SwiftUI over WatchKit. SwiftUI provides the same capabilities but with declarative syntax and automatic adaptation to screen sizes: 38 mm (272×340), 42 mm (312×390), 40 mm (324×394), 44 mm (368×448), 45 mm (396×484), 49 mm (410×502 on Apple Watch Ultra).

Background modes and power consumption

watchOS limits background app activity to save battery. Available background modes: Workout, HealthKit (health monitoring), Location (geolocation), Audio (audio player), and Complication (data on the watch face). Each mode requires a separate capability in entitlements. Typical power consumption: active app — 50-80 mA, background mode — 5-15 mA, Standby — 1-3 mA.

swift
import BackgroundTasks
import WatchKit

/// Scheduling background data updates on watchOS
class BackgroundTaskManager: NSObject {

    func scheduleBackgroundRefresh() {
        let request = BGAppRefreshTaskRequest(identifier: "com.example.refresh")
        request.earliestBeginDate = Date(timeIntervalSinceNow: 30 * 60)

        try? BGTaskScheduler.shared.submit(request)
    }

    func handleAppRefresh(task: BGAppRefreshTask) {
        task.expirationHandler = { task.setTaskCompleted(success: false) }

        DataService.shared.fetchData { result in
            switch result {
            case .success:
                ComplicationController.reloadComplications()
                task.setTaskCompleted(success: true)
            case .failure:
                task.setTaskCompleted(success: false)
            }
        }
    }
}

/// Registering a background task in WKExtensionDelegate
class ExtensionDelegate: NSObject, WKExtensionDelegate {
    let manager = BackgroundTaskManager()

    func handle(_ backgroundTasks: Set<WKBackgroundTask>) {
        for task in backgroundTasks {
            switch task {
            case let refreshTask as BGAppRefreshTask:
                manager.handleAppRefresh(task: refreshTask)
            default:
                task.setTaskCompleted(success: false)
            }
        }
    }
}

BGTaskScheduler ensures that background tasks run at optimal times — when the watch is charging and connected to iPhone. WKExtensionDelegate handles incoming background tasks and updates data on the watch face. ComplicationController.reloadComplications updates widgets on the selected watch face.

watchOS 10: Smart Stack and Double Tap

watchOS 10 — the biggest interface update in the platform's history, released in September 2023. The system shifted from hierarchical navigation to content-oriented navigation: the main screen became Smart Stack — an intelligent widget stack that replaced the app dock.

Smart Stack

Smart Stack is a vertical list of widgets displayed below the watch face. Widgets are ranked by context: weather and calendar in the morning, activity and reminders during the day, meditation and sleep preparation in the evening. Developers can add custom widgets through WidgetKit for watchOS, using the same APIs as for iOS 17.

Double Tap

Double Tap is a gesture of pinching the index finger and thumb together, recognized by the accelerometer and gyroscope without touching the screen. On Apple Watch Series 9 and Ultra 2, the gesture is handled at the hardware level via the Neural Engine. Developers receive the event through UIDoubleTapGestureRecognizer or through the SwiftUI modifier .onTapGesture(count: 2). The gesture requires no calibration and works in any hand orientation.

New APIs for developers

watchOS 10 introduced: SwiftUI Animation with Spring and Keyframe animation support, MapKit for displaying maps on the watch, VideoPlayer for playing short videos (up to 30 seconds), improved VoiceOver with gestures, and a new navigation paradigm NavigationStack instead of NavigationView.

APIPurposeAvailable since
WidgetKit for watchOSWidgets for Smart StackwatchOS 10
UIDoubleTapGestureDouble Tap gesturewatchOS 10 (S9+)
MapKitMap display on watchwatchOS 10
NavigationStackNew navigation paradigmwatchOS 10
SwiftUI KeyframeFrame-by-frame animationwatchOS 10

SwiftUI for Apple Watch

SwiftUI is the primary framework for developing watchOS interfaces. Apple recommends SwiftUI for all new projects starting with watchOS 7. SwiftUI for the watch uses the same principles as for iOS, but with watchOS-specific modifiers and components.

WatchOS-specific SwiftUI components

SwiftUI for watchOS includes: TabView with page style for swiping between screens, DigitalCrownRotation for handling the crown rotation, SceneStorage for preserving state between launches, WKNotificationScene for custom notifications, and ComplicationDescriptor for data on the watch face.

swift
import SwiftUI
import HealthKit

/// watchOS app for heart rate monitoring
@main
struct HeartMonitorApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        WKNotificationScene(
            controller: NotificationController.self,
            category: "heartAlert"
        )
    }
}

struct ContentView: View {
    @State private var heartRate: Double = 0
    private let healthStore = HKHealthStore()

    var body: some View {
        TabView {
            HeartRateView(rate: heartRate)
                .tabItem { Label("Heart Rate", systemImage: "heart.fill") }

            StepsView()
                .tabItem { Label("Steps", systemImage: "figure.walk") }

            SettingsView()
                .tabItem { Label("Settings", systemImage: "gear") }
        }
        .tabViewStyle(.page)
        .onAppear(perform: setupHealthKit)
    }

    private func setupHealthKit() {
        guard HKHealthStore.isHealthDataAvailable() else { return }
        let heartType = HKQuantityType(.heartRate)

        healthStore.requestAuthorization(toShare: nil, read: [heartType]) { success, error in
            guard success else { return }
            startHeartRateQuery()
        }
    }

    private func startHeartRateQuery() {
        let heartType = HKQuantityType(.heartRate)
        let query = HKObserverQuery(sampleType: heartType, predicate: nil) { _, _, error in
            guard error == nil else { return }
            fetchLatestHeartRate()
        }
        healthStore.execute(query)
    }

    private func fetchLatestHeartRate() {
        let heartType = HKQuantityType(.heartRate)
        let sort = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
        let query = HKSampleQuery(sampleType: heartType, predicate: nil,
                                    limit: 1, sortDescriptors: [sort]) { _, samples, _ in
            guard let sample = samples?.first as? HKQuantitySample else { return }
            let rate = sample.quantity.doubleValue(for: HKUnit(from: "count/min"))
            DispatchQueue.main.async { heartRate = rate }
        }
        healthStore.execute(query)
    }
}

struct HeartRateView: View {
    let rate: Double

    var body: some View {
        VStack(spacing: 12) {
            Image(systemName: "heart.fill")
                .foregroundStyle(.red)
                .font(.system(size: 48))
                .symbolEffect(.pulse)

            Text("\(Int(rate))")
                .font(.system(.title, design: .rounded))
                .contentTransition(.numericText())
                .bold()

            Text("bpm")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
    }
}

The HeartMonitorApp demonstrates a typical watchOS app structure in SwiftUI: TabView with page style for swiping between screens, HealthKit integration for real-time heart rate reading, WKNotificationScene for handling notifications. SymbolEffect with pulse animation uses Neural Engine hardware acceleration for smooth animation without CPU overhead.

Digital Crown and gestures

The Digital Crown is the wheel on the side of the Apple Watch. SwiftUI provides DigitalCrownRotation for binding a value to the crown rotation. The modifier accepts a binding, range, and step. Gestures: tap, longPress, swipe, and pan — all standard for SwiftUI and adapted to the watch screen size.

WatchKit and watchOS App Components

WatchKit is the original watchOS framework using a UIKit approach. Although Apple recommends SwiftUI, WatchKit remains relevant for legacy projects and specific tasks: complex animations on WKInterfaceGroup and SiriKit integration.

watchOS app structure

A watchOS app consists of two targets: WatchKit Extension (logic and interface) and iOS Companion App (settings and synchronization). Starting with Xcode 15, it is possible to create a standalone app without an iOS companion. The interface is described in Interface.storyboard (WatchKit) or programmatically via SwiftUI.

ComponentWatchKitSwiftUI
ScreenWKInterfaceControllerView
ButtonWKInterfaceButtonButton
TableWKInterfaceTableList
GroupWKInterfaceGroupVStack / HStack
ImageWKInterfaceImageImage / AsyncImage
LabelWKInterfaceLabelText
MapWKInterfaceMapMap (watchOS 10+)
ComplicationCLKComplicationDataSourceComplicationDescriptor

Complications — data on the watch face

A Complication is a widget that displays data on the Apple Watch face. The developer implements the CLKComplicationDataSource protocol, providing templates for different watch face types (circular, rectangular, modular, extraLarge). watchOS 10 supports ComplicationDescriptor — a simplified API for SwiftUI. Data is updated via Background Tasks with a period of up to 30 minutes.

iPhone Integration via Watch Connectivity

Watch Connectivity is a framework for exchanging data between Apple Watch and iPhone via Bluetooth or Wi-Fi. It is the only communication method between paired devices. WCSession is the central class managing the session. The iOS app and watchOS extension must implement WCSessionDelegate.

Data transfer methods

Watch Connectivity provides four data transfer methods: sendMessage — immediate sending with acknowledgment (works only when both apps are active), transferUserInfo — background delivery of a data dictionary, transferFile — file transfer with metadata, updateApplicationContext — synchronization of shared state. All methods guarantee delivery when the connection is restored.

swift
import WatchConnectivity

/// Sync manager between iPhone and Apple Watch
final class ConnectivityManager: NSObject, WCSessionDelegate {

    static let shared = ConnectivityManager()
    private let session = WCSession.default

    override private init() {
        super.init()
        session.delegate = self
        session.activate()
    }

    // MARK: — Sending data from iPhone to watch
    func sendWorkoutData(_ data: [String: Any]) {
        guard session.isReachable else {
            // If watch is unavailable — save to context
            try? session.updateApplicationContext(data)
            return
        }
        session.sendMessage(data, replyHandler: nil) { error in
            print("Send error: \(error.localizedDescription)")
        }
    }

    // MARK: — Receiving data on watch
    func session(_ session: WCSession,
                 didReceiveMessage message: [String: Any]) {
        DispatchQueue.main.async {
            NotificationCenter.default.post(
                name: NSNotification.Name("dataReceived"),
                object: message
            )
        }
    }

    func session(_ session: WCSession,
                 activationDidCompleteWith activationState: WCSessionActivationState,
                 error: Error?) {
        print("WCSession activated: \(activationState.rawValue)")
    }

    // Not required on watchOS but mandatory for protocol
    func sessionDidBecomeInactive(_ session: WCSession) {}
    func sessionDidDeactivate(_ session: WCSession) {
        session.activate()
    }
}

ConnectivityManager implements a singleton for working with WCSession. sendWorkoutData checks isReachable: if the watch is active, data is sent immediately via sendMessage; if not, it is saved to applicationContext for deferred delivery. onReceiveMessage on the receiving side processes incoming messages and notifies the app via NotificationCenter.

File exchange and synchronization

transferFile allows transferring large amounts of data: images, audio files, archives. Maximum file size is 100 MB. Files are saved to the Inbox directory on the receiving device. transferUserInfo is suitable for JSON data up to 100 KB. All methods work in the background: if the device is unavailable, the transfer is queued and automatically resumes when the connection is restored.

Publishing watchOS Apps

Publishing a watchOS app follows the same rules as iOS: an Apple Developer Program subscription ($99/year) is required, along with App Review moderation. The app is uploaded to App Store Connect as part of an iOS app or as a standalone app.

Build and distribution

A watchOS app can be delivered in two ways: as a built-in iOS app extension (the iOS app bundle contains the watchOS .app) or as a standalone app (downloaded and runs without iPhone). For standalone mode, WKRunsIndependently = YES is required in Info.plist. The watchOS app size is limited to 50 MB for cellular downloads.

App Review requirements

Special requirements for watchOS: the app must work correctly without an active iPhone (if claimed as standalone), the interface must be readable without zooming, all interactive elements must be at least 44 points in size. Apps that duplicate built-in functionality (e.g., a heart rate monitor without added value) are prohibited.

RequirementDescription
App sizeUp to 50 MB for cellular download, up to 4 GB via Wi-Fi
Standalone modeWKRunsIndependently = YES in Info.plist
Touch targetsMinimum 44 pt for all interactive elements
SecurityHealthKit data cannot be sent to server without consent
PerformanceApp launch no more than 5 seconds

Frequently Asked Questions

What languages are used for watchOS development?

The primary language is Swift with the SwiftUI framework. WatchKit on UIKit is also supported, but Apple recommends SwiftUI for all new watchOS projects. Objective-C is only used in legacy apps released before 2019. Since watchOS 7, all Apple examples exclusively use SwiftUI.

Is an iPhone required for a watchOS app to work?

Starting with watchOS 6, Apple Watch can install apps directly from the App Store without an iPhone. However, many features — data synchronization, push notifications, geolocation — require pairing with an iPhone. Fully standalone apps are possible with watchOS 9 and WKRunsIndependently in build settings.

What is the battery life of Apple Watch with an active app?

Typical Apple Watch Series 9 battery life is up to 18 hours in mixed mode. With active GPS and heart rate monitor usage — 5-7 hours. watchOS 10 optimizes power consumption through Smart Stack and BGTaskScheduler, reducing background app activity by up to 4 times compared to watchOS 9.

How to transfer data between iPhone and Apple Watch?

The Watch Connectivity framework provides four methods: sendMessage (immediate transfer), transferUserInfo (background), transferFile (files up to 100 MB), and updateApplicationContext (state synchronization). All methods work via Bluetooth or Wi-Fi with automatic queuing when the connection is lost.

What sensors are available on Apple Watch?

Apple Watch Series 9 and Ultra 2 include: accelerometer, gyroscope, optical and electrical heart rate sensor, SpO2 (saturation), wrist temperature sensor, barometer, compass, GPS L1+L5, and microphone. Sensor access is through HealthKit and Core Motion. Heart rate and SpO2 data require explicit user permission.

Summary

  • watchOS — Apple's operating system for smartwatches on the XNU kernel, focused on energy efficiency and iPhone integration
  • SwiftUI — the primary framework for watchOS, providing declarative layout and automatic screen size adaptation
  • watchOS 10 introduced Smart Stack, Double Tap (S9+), NavigationStack, and WidgetKit for widgets
  • Watch Connectivity — the only communication channel with iPhone via Bluetooth/Wi-Fi with four transfer modes
  • HealthKit provides access to Apple Watch sensors: heart rate, SpO2, temperature, accelerometer, GPS
  • Complications — watch face widgets implemented via CLKComplicationDataSource or SwiftUI
  • Publishing requires Apple Developer Program, size up to 50 MB (cellular) and strict performance control

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also