Getting Started with HealthKit

Rightpoint
Rightpoint
Published in
5 min readApr 17, 2020

Out of sheer curiosity, I often find myself checking my daily step count on Apple’s Health app. In an attempt to get a basic intro to Swift, I sought out to replicate this functionality by creating my own custom application. In this post, I’m going to walk through how to display the number of steps a user has taken today using HealthKit. However, this article just scratches the surface of all HealthKit has to offer. Check out the documentation if you’re interested in acquiring other health-related data types.

Before we get started, I recommend having a physical iPhone (rather than the virtual simulator) to use in testing the app, as the simulator will always return a step count of zero.

Start by creating an empty, single-view application in Xcode. Once we have that, we can take a couple preliminary steps to tell our application that we want to use HealthKit to access the user’s health data.

First, we should turn on HealthKit in the Capabilities section of the app’s settings.

Next, we need to add two properties to the Info.plist file. The two keys that we need to specify are:

  • Privacy — Health Share Usage Description
  • Privacy — Health Update Usage Description

The description in the Value field is shown to the user when the app requests access to the user’s health data. (We can leave the Type field as the default String value.)

Once we’ve turned on HealthKit in the app’s capabilities and have specified those two properties in Info.plist, we can begin to dive into the code. Please note that for simplicity’s sake, I’ll be putting all of the code in the default view controller in this brief walkthrough. In a production application, however, it is typically best practice to avoid leaving all of your code in a single file.

Our next step is to open Main.Storyboard, add a UILabel, and create an outlet for the label in ViewController.swift. Any name should do, but for this example, I used stepsLabel.

At the top of our view controller, we need to add an import statement for HealthKit. Then, we need to declare a new global variable, named healthStore in this example. Its value should be set to HKHealthStore(). This HKHealthStore object will provide us with the user’s step count.

Since health-related information is private (by default) to the user, we need to ask the user for their permission to access it. This relates back to the set-up we did inside of the Info.plist file. We can do this within the viewDidLoad() method of the view controller. This will open up a dialog when the user opens the app, which will ask for permission to access the user’s health data.

// Access Step Count 
let healthKitTypes: Set = [ HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)! ]
// Check for Authorization
healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (success, error) in
if (success) { // Authorization Successful
self.getSteps { (result) in
DispatchQueue.main.async {
let stepCount = Int(result)
self.stepsLabel.text = String(stepCount)
}
} } // end if } // end of checking authorization

Let’s break this code block down into a few key parts.

The top line (where we set the healthKitTypes variable) states that we want to specifically access the user’s step count. (Again, if you’re interested in other data types, you can list multiple types here, but for this app, we only want to access the user’s step count.)

After stating our desired type(s), we request authorization. If the request is successful, we can then query the HealthKit store for data. Once we get a result back, we can set our label’s text property to the resulting step count.

In this example, the query is constructed in a separate method, named getSteps. (This method’s full signature is func getSteps(completion: @escaping (Double) -> Void).)

let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!let now = Date()
let startOfDay = Calendar.current.startOfDay(for: now)
var interval = DateComponents()
interval.day = 1

At the beginning of the getSteps method, we declare and initialize a few variables that will be used to construct our query. In the code above, we set a variable (stepsQuantityType) to the quantityType that we requested access to earlier in the viewDidLoad method. We also need to specify a start and end time, as we are attempting to get the number of steps taken within a given time span. In this example, we are fetching the number of steps taken in the present day, so we get the current date/time information, as well as the date/time information for the start of the current day (i.e. midnight of the current day).

let query = HKStatisticsCollectionQuery( 
quantityType: stepsQuantityType,
quantitySamplePredicate: nil,
options: [.cumulativeSum],
anchorDate: startOfDay,
intervalComponents: interval)

Directly below those variable declarations (still inside of the getSteps method), we can create the query object, as shown above. Here, we are using an HKStatisticsCollectionQuery. This query object will grab the user’s latest step count throughout the day.

query.initialResultsHandler = { _, result, error in 
var resultCount = 0.0
result!.enumerateStatistics(from: startOfDay, to: now) { statistics, _ in
if let sum = statistics.sumQuantity() {
// Get steps (they are of double type)
resultCount = sum.doubleValue(for: HKUnit.count())
} // end if
// Return
DispatchQueue.main.async {
completion(resultCount)
}
}
}

After declaring the query, we set up the initialResultsHandler, which returns, as you may have guessed, the query’s initial results. In this block of code, we simply get and return the user’s step count.

query.statisticsUpdateHandler = {     query, statistics, statisticsCollection, error in 
// If new statistics are available
if let sum = statistics?.sumQuantity() {
let resultCount = sum.doubleValue(for: HKUnit.count())
// Return
DispatchQueue.main.async {
completion(resultCount)
}
} // end if
}

In order to get the most up-to-date step count, we should add the statisticsUpdateHandler, which monitors the HealthKit store and updates the count if new data becomes available.

healthStore.execute(query)

Lastly, at the bottom of the getSteps method, we execute the query.

If you were following along, try now running the app, allow the app to access your health data (only if you want to), and you should see the number of steps that you’ve taken today (while you were carrying your iPhone/wearing your Apple Watch).

In closing, I’d like to reiterate that HealthKit offers a wide array of data types. If you’re interested, check out the documentation to see the growing list of information that you may find useful in building your next health/fitness app.

--

--