Step Counter in HealthKit

Become a Subscriber

HealthKit is a beast of an SDK and the documentation and available tutorials are few and far between. In this tutorial we are going to do just a few basic things with HealthKit: authorize and request the steps for the last 24 hours.

Enabling HealthKit in your Swift Application

Enable HealthKit iOS

This one is pretty simple. Click on your main project in the Project Navigator (left sidebar, top most file) and then on the main view select the Capabilities tab. Scroll down and toggle HealthKit on and your app will install the entitlement, info.plist and framework automatically.

Authorizing Access to HealthKit in Swift

Let’s create a new class called HealthKitHelper and drop in our imports:

import Foundation
import HealthKit

class HealthKit 
{
  // Future code here
}

Now let’s stub out our class. Here’s what we’ll need:

  • a variable to access our HKHealthStore instance (HKHealthStore provides an interface for accessing and storing the user’s health data)
  • an init that checks authorization
  • a checkAuthorization method
  • a recentSteps method
import Foundation
import HealthKit

class HealthKit
{
  let storage = HKHealthStore()

  init()
  {
    checkAuthorization()
  }

  func checkAuthorization() -> Bool {}

  func recentSteps(completion: (Double, NSError?) -> () ) {}
}

Now we’re ready to do some real work. First, let’s complete our checkAuthorization method:

func checkAuthorization() -> Bool
{
  // Default to assuming that we're authorized
  var isEnabled = true

  // Do we have access to HealthKit on this device?
  if HKHealthStore.isHealthDataAvailable()
  {
    // We have to request each data type explicitly
    let steps = NSSet(object: HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount))

    // Now we can request authorization for step count data
    storage.requestAuthorizationToShareTypes(nil, readTypes: steps) { (success, error) -> Void in
      isEnabled = success
    }
  }
  else
  {
    isEnabled = false
  }

  return isEnabled
}

Fetch daily step count from HealthKit

It’s worth noting that we can also get step count data from CoreMotion, but since we are focused on HealthKit for this tutorial, I’m not going into that. If you interested in the pros and cons of CoreMotion vs HealthKit for this type of data specifically, check out PunchKick’s blog post on the subject.

func recentSteps(completion: (Double, NSError?) -> () )
{
  // The type of data we are requesting (this is redundant and could probably be an enumeration
  let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)

  // Our search predicate which will fetch data from now until a day ago 
  // (Note, 1.day comes from an extension
  // You'll want to change that to your own NSDate
  let predicate = HKQuery.predicateForSamplesWithStartDate(NSDate() - 1.day, endDate: NSDate(), options: .None)

  // The actual HealthKit Query which will fetch all of the steps and sub them up for us.
  let query = HKSampleQuery(sampleType: type, predicate: predicate, limit: 0, sortDescriptors: nil) { query, results, error in
    var steps: Double = 0

    if results?.count > 0
    {
      for result in results as [HKQuantitySample]
      {
        steps += result.quantity.doubleValueForUnit(HKUnit.countUnit())
      }
    }

    completion(steps, error)
  }

  storage.executeQuery(query)
}

Now we are ready to fetch some data in our application. Wherever appropriate in your own application, go ahead and call our new method:

HealthKit().recentSteps() { steps, error in
  \\ do something with steps
}

Wrapping Up

HealthKit is big, and there are many different constant-defined units throughout. The SDK gets to be a bit verbose and redundant, so I find myself wrapping the requests and various endpoints in enumerations or structs. Don’t forget to dispatch these requests asynchronously, as many of them can be slow and will definitely hinder your application if your UI is waiting for the results.