Creating an iOS App to Display the Number of Steps Taken Today

Matthew Bennett
5 min readOct 1, 2018
“Apple Center” by zhang kaiyv on Unsplash

Hi.

In this post, I’m going to walk you through how I was able to (and how you can) display the number of steps the user has taken in the present day.

I often find myself on Apple’s Health app to see how many steps I’ve taken (just out of curiosity) and wanted to replicate that functionality using HealthKit. (However, if you’re interested in acquiring additional/other health-related information, HealthKit provides a plethora of data types.)

I used Xcode and Swift to create the app and an iPhone to test it. (You can use a Simulator from Xcode on a Mac, but it doesn’t have step count data, so I suggest that you use a physical device.)

To get started, we need to create a new Xcode project (a single-view application will do for this walkthrough).

Before writing any code, we need to take a couple preliminary steps to get access to the HealthKit framework.

First, we need to explicitly state that we are going to use HealthKit in the app.

We can do this by going into the app’s General settings, clicking on the “Capabilities” tab, and turning on HealthKit.

Next, we need to edit Info.plist.

We need to add a property for each health-related Key:

  • Privacy - Health Share Usage Description
  • Privacy - Health Update Usage Description

The description in the Value field is shown to the user to give an explanation as to why we want to use these fields. (We can leave the Type field as the default String for each property.)

After correctly setting the HealthKit options, we can add a UILabel (named stepsLabel in this example) to Main.Storyboard and create an outlet for that label in ViewController.swift.

Next, we need to add an import statement for HealthKit at the top of ViewController.swift. We also need to declare a new global variable (named healthStore in this example). Its value should be set to HKHealthStore(). The HKHealthStore is the object that will provide us with the user’s step count.

Since health-related information is often sensitive, we need to ask the user for his/her permission to see if we’re even allowed to access it. We can do this within the viewDidLoad() method. This will cause the application to ask for permission to access HealthKit when the user opens the app.

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

The first line (where we set healthKitTypes) states that we want to access the user’s step count. (You can list multiple types that you want to access in this statement, but for this app, we only need to access the user’s step count.)

After setting our desired type(s), we then request authorization for said type(s). If our request is successful, we can then query the HealthKit store for data and set the label’s text to be the user’s step count.

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

let type = HKQuantityType.quantityType(forIdentifier: .stepCount)!

let now = Date()
let startOfDay = Calendar.current.startOfDay(for: now)
var interval = DateComponents()
interval.day = 1

In the first lines of the getSteps method, we want to declare and initialize variables that will be used to construct the query. In the code above, we need to set a variable (type) to the quantityType that we set earlier in the viewDidLoad method. We also need to get the current date/time information, the startOfDay of that information (12 AM of the present day), and set our time interval to be one day (max).

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

After setting up the variables, we can create the query object (in the same method). For this app, I chose to use an HKStatisticsCollectionQuery. The reason I chose to use this object, rather than an HKStatisticsQuery, is that the former allows for an update handler, which is used to update the user’s step count more frequently throughout the day.

While testing the application using HKStatisticsQuery (the object I chose originally), I found that it would often take significantly longer for the step count to update on this app than it takes the Health app to update.

(I actually found on several occasions that if I would close this app, open the Health app, then switch back to this app, I would have an updated count.)

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)
}
}
}

Below the query declaration, we can set up the initialResultsHandler. This handler returns, as you may have guessed, the query’s initial results. In this block of code, we get the user’s step count and return the value.

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
}

Next, we want to add the statisticsUpdateHandler, which, as mentioned before, monitors the HealthKit store and updates the step count if new data becomes available.

healthStore.execute(query)

Finally, at the bottom of this method, we need to execute the query.

After following these instructions, I was able to display the number of steps that the user has taken in the present day.

I hope you learned something.

If you noticed anything in here that could be improved (the overall strategy, a single line of code, or even the way I explained something), please let me know.

--

--