Introduction
In this tutorial, you'll learn how to develop a smartwatch application using Apple's WatchKit framework that can access health data from the Apple Watch Series 11. The Apple Watch Series 11 introduced enhanced health tracking capabilities including heart rate monitoring, ECG functionality, and improved battery life. We'll create a basic health dashboard that displays heart rate data using the HealthKit framework, which is accessible through WatchKit applications.
This tutorial builds upon your existing knowledge of iOS development and will teach you how to integrate with Apple's health ecosystem to create meaningful health tracking applications.
Prerequisites
- Basic understanding of Swift programming language
- Xcode 15 or later installed
- Apple Watch Series 11 or later simulator
- Basic knowledge of iOS app development concepts
- Apple Developer account (for testing on physical devices)
Step-by-Step Instructions
1. Create a New WatchKit App Project
First, we need to set up our development environment with a new WatchKit application. This project will contain both the iOS app and the WatchKit extension that will run on the Apple Watch.
1. Open Xcode
2. Select "Create a new Xcode project"
3. Choose "App" under iOS templates
4. Name your project "HealthDashboard"
5. Select "Swift" as language and "SwiftUI" as interface
6. Make sure "Include WatchKit App" is checked
7. Click "Next" and create the project
Why: Creating a WatchKit project with both iOS and WatchKit components allows us to build a complete application that can communicate between the iPhone and the watch, which is essential for health data access.
2. Configure HealthKit Permissions
HealthKit is Apple's framework for accessing health data. We need to request appropriate permissions for our application to access heart rate data.
1. Open the WatchKit Extension target in your project
2. Go to the "Signing & Capabilities" tab
3. Click the "+" button to add a new capability
4. Search for "HealthKit" and add it
5. Open the Info.plist file and add the following key:
<key>NSHealthShareUsageDescription</key>
<string>This app needs access to your heart rate data to display health metrics</string>
<key>NSHealthUpdateUsageDescription</key>
<string>This app needs permission to update health data</string>
Why: HealthKit requires explicit user permission to access health data. These descriptions will be shown to users when they're prompted for permission, explaining why your app needs access to their health information.
3. Set Up HealthKit Data Access
Now we'll implement the core functionality to access heart rate data from HealthKit.
import HealthKit
class HealthDataManager {
private let healthStore = HKHealthStore()
private let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
func requestAuthorization(completion: @escaping (Bool, Error?) -> Void) {
let typesToShare: Set = []
let typesToRead: Set = [heartRateType]
healthStore.requestAuthorization(toShare: typesToShare, read: typesToRead) { success, error in
DispatchQueue.main.async {
completion(success, error)
}
}
}
func fetchHeartRateData(completion: @escaping ([HKSample]?, Error?) -> Void) {
let now = Date()
let startDate = Calendar.current.date(byAdding: .hour, value: -1, to: now)!
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: now, options: .strictStartDate)
let query = HKSampleQuery(sampleType: heartRateType, predicate: predicate, limit: 100, sortDescriptors: nil) { query, samples, error in
completion(samples, error)
}
healthStore.execute(query)
}
}
Why: This class encapsulates all HealthKit operations. It handles authorization requests and data fetching, which are essential components for any health tracking application. The time window is set to the last hour to provide recent data.
4. Create the WatchKit Interface
Next, we'll design the user interface for our health dashboard that will display the heart rate data.
import SwiftUI
import WatchKit
struct HeartRateView: View {
@State private var heartRateData: [Double] = []
@State private var isLoading = false
var body: some View {
VStack(spacing: 10) {
Text("Recent Heart Rate")
.font(.title2)
.bold()
if isLoading {
ProgressView()
.scaleEffect(1.5)
} else if heartRateData.isEmpty {
Text("No data available")
.foregroundColor(.secondary)
} else {
Text("\(heartRateData.last ?? 0, specifier: "%.0f") BPM")
.font(.largeTitle)
.bold()
Text("Last updated: \(formatDate(Date()))")
.font(.caption)
.foregroundColor(.secondary)
}
}
.onAppear {
loadHeartRateData()
}
}
private func loadHeartRateData() {
isLoading = true
let healthManager = HealthDataManager()
healthManager.fetchHeartRateData { samples, error in
DispatchQueue.main.async {
isLoading = false
if let samples = samples as? [HKQuantitySample] {
self.heartRateData = samples.map { $0.quantity.doubleValue(for: HKUnit.count().unitDivided(by: HKUnit.minute())) }
}
}
}
}
private func formatDate(_ date: Date) -> String {
let formatter = DateFormatter()
formatter.timeStyle = .short
return formatter.string(from: date)
}
}
Why: This SwiftUI view creates a clean, readable interface for displaying heart rate data. It includes loading states and proper data formatting to provide a good user experience.
5. Implement the WatchKit Extension
Finally, we need to connect our HealthKit data to the WatchKit interface.
import WatchKit
import Foundation
class InterfaceController: WKInterfaceController {
@IBOutlet var heartRateLabel: WKInterfaceLabel!
@IBOutlet var lastUpdatedLabel: WKInterfaceLabel!
private let healthManager = HealthDataManager()
override func awake(withContext context: Any?) {
super.awake(withContext: context)
// Request HealthKit authorization
healthManager.requestAuthorization { success, error in
if success {
self.loadHeartRateData()
} else {
print("HealthKit authorization failed: \(error?.localizedDescription ?? "Unknown error")")
}
}
}
private func loadHeartRateData() {
healthManager.fetchHeartRateData { samples, error in
DispatchQueue.main.async {
if let samples = samples as? [HKQuantitySample] {
if let lastSample = samples.last {
let heartRate = lastSample.quantity.doubleValue(for: HKUnit.count().unitDivided(by: HKUnit.minute()))
self.heartRateLabel.setText("\(Int(heartRate)) BPM")
self.lastUpdatedLabel.setText("Updated \(self.formatDate(Date()))")
}
}
}
}
}
private func formatDate(_ date: Date) -> String {
let formatter = DateFormatter()
formatter.timeStyle = .short
return formatter.string(from: date)
}
}
Why: This extension connects the HealthKit data to the WatchKit interface. It handles the authorization flow and displays the heart rate data in a user-friendly format, which is essential for any health tracking application.
Summary
In this tutorial, you've learned how to create a smartwatch application that accesses health data from Apple Watch Series 11 devices. You've implemented HealthKit integration to fetch heart rate data, created a user interface to display this information, and handled the necessary permissions. This foundation can be expanded to include other health metrics like ECG data, sleep tracking, or workout monitoring that are available on the Apple Watch Series 11.
The key concepts covered include HealthKit authorization, data fetching with proper time predicates, and displaying health information on a watch interface. This approach follows Apple's guidelines for health data access and provides a solid foundation for more complex health tracking applications.



