HealthKit: Getting Fitness Data

This is the last installment in my series about HealthKit as we’re approaching the New Year and the release of the WATCH, especially the Sports edition. Make sure to take a look at my two previous posts about HealthKit:

Now, let’s talk about the heart of HealthKit – getting your user’s health data.


In case you haven’t read my HealthKit: Asking For Identifying Information post yet, the HKHealthStore class provides an interface for accessing and storing the user’s health data. Since this is what you’re using to read and write from the HealthKit database, it’s best to just create this once. I like to wrap by healthStore constant in a singleton, which I use to interface with HealthKit.

let healthStore: HKHealthStore? = {
    if HKHealthStore.isHealthDataAvailable() {
        return HKHealthStore()
    } else {
        return nil

Note that the HealthStore is not available on all devices, so make sure to do an HKHealthStore.isHealthDataAvailable() check when instantiating your healthStore constant.


As mentioned in my HealthKit: Let’s Talk About Units post, HKQuantity is a standardized way to talk about an amount of a specific unit (e.g. 120lb).

HKQuantityType helps us specify what exactly this quantity is referring to. For example, 120lb could be referring to someone’s weight or to how much weight they bench-pressed this morning at the gym.

In this post, I’ll focus on the getting the user’s step data:

let stepsCount = HKQuantityType.quantityTypeForIdentifier(

This same code can be applied to all the other types of quantifiable Health data:

Asking for Permission

Just like with the user’s identifying information, we have to ask the user for permission to both READ and WRITE their HKQuantityType data.

let healthStore: HKHealthStore? = {
        if HKHealthStore.isHealthDataAvailable() {
            return HKHealthStore()
        } else {
            return nil

let stepsCount = HKQuantityType.quantityTypeForIdentifier(

let dataTypesToWrite = NSSet(object: stepsCount)
let dataTypesToRead = NSSet(object: stepsCount)   

readTypes: dataTypesToRead,
completion: { [unowned self] (success, error) in
            if success {
            } else {

Now, when the user runs the app for the first time, they’ll see this screen pop up:

Notice that the user has very granular control over the permissions. They have to decide whether they want to allow you to just read their data or write to it! It is best practice to keep your READ and WRITE permissions separate. Really think about what your actually NEED for your app, and out of that whether you need both READ and WRITE permissions for each piece of data. The more data you ask for, the more the user has time to reconsider allowing permissions for your app!

Check out how overwhelming this page can get just with a few additional permission requests:

HealthKit Permissions Fitness


To READ data from the HealthStore, simply create a query and execute it:

let stepsCount = HKQuantityType.quantityTypeForIdentifier(

let stepsSampleQuery = HKSampleQuery(sampleType: stepsCount,
    predicate: nil,
    limit: 100,
    sortDescriptors: nil)
    { [unowned self] (query, results, error) in
        if let results = results as? [HKQuantitySample] {
            self.steps = results

// Don't forget to execute the Query!

The HKSampleQuery can get very specific – you can ask for data with a specific filter and sorted in a specific order. The main thing to remember, though, is to make sure to execute the query!

If the user didn’t give you READ permissions for the data you’re asking, an empty results array is returned. If you do have READ permissions and the user has data entered, then you get back an array of HKQuantitySamples.


An HKQuantitySample is the combination of an HKQuantity (e.g. 2,000 count) and an HKQuantityType (e.g. HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount). After all, you need to know what the quantity is referring to in terms of Health Data.


Note that HKQuantitySample inherits from HKSample:


This gets you the start and end date for your data point! Now you can enough information to populate a UITableViewCell with step and date data:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(stepCellIdentifier) as UITableViewCell

    let step = steps[indexPath.row]
    let numberOfSteps = Int(step.quantity.doubleValueForUnit(HKUnit.countUnit()))

    cell.textLabel.text = "\(numberOfSteps) steps"
    cell.detailTextLabel?.text = dateFormatter.stringFromDate(step.startDate)

    return cell

The result is this in my case:

Steps Info

Hopefully you can come up with much cooler UI, especially for the WATCH!


HealthKit also allows running of a statistical query. In my case, I’m just going to get the total steps the user has ever taken:

let stepsCount = HKQuantityType.quantityTypeForIdentifier(

let sumOption = HKStatisticsOptions.CumulativeSum

let statisticsSumQuery = HKStatisticsQuery(quantityType: stepsCount, quantitySamplePredicate: nil,
    options: sumOption)
    { [unowned self] (query, result, error) in
        if let sumQuantity = result?.sumQuantity() {
            let headerView = self.tableView.dequeueReusableCellWithIdentifier(self.totalStepsCellIdentifier) as UITableViewCell

            let numberOfSteps = Int(sumQuantity.doubleValueForUnit(self.healthKitManager.stepsUnit))
            headerView.textLabel.text = "\(numberOfSteps) total"
            self.tableView.tableHeaderView = headerView


// Don't forget to execute the query!

The result is that I can now see the total number of steps in the header of my table view:

Total Steps

In addition to the CumulativeSum, you can also get the min, max, average, and data separated by source:


One thing I’d like to point out is that at this time, Querying HealthKit is very very slow! So make sure you have clear indicators for your user’s that the query is actually happening, or consider querying in the background.

Writing (aka Sharing) Data

When we did a query for steps data, we got back an array of HKQuantitySamples. To WRITE data to the HealthKit database, we need to convert our data (3000 steps taken today) into an HKQuantitySample:

let stepsQuantityType = HKQuantityType.quantityTypeForIdentifier(

let stepsUnit = HKUnit.countUnit()
let stepsQuantity = HKQuantity(unit: stepsUnit,
    doubleValue: 3000)

let stepsQuantitySample = HKQuantitySample(
    type: stepsQuantityType,
    quantity: stepsQuantity,
    startDate: NSDate(),
    endDate: NSDate())

Now you can WRITE your HKQuantitySample object to the HealthKit database, but only if the user has given you permission!

if let authorizationStatus = healthStore?.authorizationStatusForType(stepsQuantityType) {

    switch authorizationStatus {

    case .NotDetermined:

    case .SharingDenied:

    case .SharingAuthorized:
        healthStore?.saveObject(stepsQuantitySample, withCompletion: { (success, error) -> Void in
            if success {
                // handle success
            } else {
                // handle error

If you’re successful in writing the data point, the user will be able to fully control it in Apple’s Health app:

Note that the user can decide to delete your data point at any time! Or any other data point for that matter.


I’d like to leave you with a famous quote from Spiderman:

“With great power comes great responsibility.”

HealthKit has a lot of potential, and can really change how consumers think about their Health, especially with the upcoming release of the WATCH. But it all depends on user trust. When developing with HealthKit, remember to really honor the user. Ask only for the data you need, and treat the data with the outmost care. This is really personal data that the user is entrusting you with!

You can view the demo project from this post on Github here. As I mentioned earlier, querying HealthKit data is very very slow at the moment, so don’t be surprised if it takes a long time for the data to populate in the demo project!

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.