How to write data to the Health App using HealthKit and HealthStore

Richard Poutier
7 min readMar 31, 2018

This lesson tutorial covers the integration of the Apple HealthKit Framework. Please comment any questions and if you found value in the content, please like or share!

This lesson is written for swift developers who already know plenty of the frameworks available in Swift but are starting to dip into HealthKit. I try and write lessons or tutorials that simplify the process of going through the documentation and then executing the code. In my honest opinion, you should read a frameworks documentation guideline before working with that new framework. In roughly an hour or so, I was able to go through the HealthKit documentation, found here, and grasp exactly what’s needed for the specific projcet I was hired to complete.

I just finished a client project on UpWork.com. The project was a simple two page application that monitored water intake levels throughout the day. Users would select the appropriate amount of water they’ve drank, and those levels get inputted into the iOS Native “Health” app.

UpWork is a website where freelancers get matched up with clients who are looking for specific type of tasks or projects to be completed. Sometimes its just reviewing an integration of an API, other times, its building out a full mvp.

Step 1: Create Your Project

Before we start integrating the HealthKit framework, we need to add some keys to our info.plst, and we need to add HealthKit to the project target capabilities.

Add Keys to Info.plst

Open up Xcode and create a new single-page-app. Next, let’s set up our HealthKit framework right away. We have to add two key-value entries into our info.plst. One is for writing data to HKHealthStore, and the other is for reading data back from it. Make sure you you add a description for your keys, this is the description the user will see when the app first launches and requests permision to read/write. The two keys to add are “Privacy — Health Share Usage Description” & “Privacy — Health Update Usage Description.”

You can see the description as the value in the key/value paring

Add HealthKit to Project Capabilites

Go to your project capabilities, and turn on HealthKit. This will add the necessary entitlements files and link up the HealthKit framework. That should complete the necessary preliminary work, now we can start coding.

Step 2: Confirm HealthKit is available, instantiate a HealthStore Object, Request Authorization

HealthKit is not available on all iOS devices. For instance, HealthKit is not available on iPad, so all other HealthKit methods fail with an errorHealthDataUnavailable error. In your AppDelegate, add the following. Use isHealthDataAvailable() when you want to access HealthKit methods or data in your app.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {  //  add this to make sure HealthKit is available
if HKHealthStore.isHealthDataAvailable() {
// add code to use HealthKit here...

}
return true
}

Now we’re going to instantiate our HealthStore Object. Add a HKHealthStore optional declaration in your AppDelegate. Then inside of your didFinishLaunchingWithOptions, initialize your healthStore object. See below…

We have one last thing to add in our AppDelegate. update your code to match below.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {//  add this to make sure HealthKit is available
if HKHealthStore.isHealthDataAvailable() {
// add code to use HealthKit here...
... // set root view controller's healthStore reference to app delegate's healthStore Instance
if let vc = self.window?.rootViewController as? ViewController {
vc.healthStore = self.healthStore
} else {
NSLog("unable to get rootViewControler")
}
}return true
}

You need only a single HealthKit store per app. These are long-lived objects. Although we haven’t technically added a healthStore reference in our ViewController class, we are going to access our rootViewController and assign it’s healthStore reference to equal the one we just created. Now, we can go update our code in ViewController so that it can receive this reference assignment. Once we have our proper reference, we can request authorization from within the viewDidAppear() method in ViewController.

Lastly, we have to request authorization to write data using the healthStore instance we just initialized. In order to request authorization from our healthStore object, we need to first create the Set of HKSampleTypes that we are going to be requesting write permissions from. Update your ViewController to match what I have below.

import UIKit
import HealthKit
class ViewController: UIViewController { var healthStore: HKHealthStore? var typesToShare : Set<HKSampleType> { let waterType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)! return [waterType]
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Request access to write dietaryWater data to HealthStore
self.healthStore?.requestAuthorization(toShare: typesToShare, read: nil, completion: { (success, error) in
if (!success) {
// request was not successful, handle user denial
return
}
})
}
}

Since requestAutorization asks us for a Set<HKSampleType> object for both toShare and read paramenters. We define a computed variable typesToShare which returns a set of HKSampleTypes, Set<HKSampleType>. Inside, we create a HealthKit ObjectType that refrences a quantity of dietaryWater. Now, when we call requestAutorization on our healthStore reference, we pass typesToShare in the toShare parameter. HealthKit now knows we want to write dietaryWater data to the HealthApp and it will appropriately prompt the user for permission. If you added any descriptions to your key tags in your info.plst, this is where they will be displayed to the user.

If you build and run your app now, you should see an empty screen but be promoted to grant Health Access for your app. Something like this…

Great!

All that we have left is to define a method that takes an amount of water in ounces, and writes that data to our health Store app. So far, if you have any questions about this lesson, feel free to refer to the Apple Developer Documentation here at any time.

Let’s write a method called “addWaterDataToHealthStore”. This method will take a Double as a parameter representing the amount of water to write to the healthStore.

Feel free to add some UI to your ViewController. You can link up some buttons to IBActions that then call addWaterDataToHealthStore().

Add the following method to your ViewController.

func addWaterAmountToHealthKit(ounces : Double) {
// 1
let quantityType = HKQuantityType.quantityType(forIdentifier: .dietaryWater)

// string value represents US fluid
// 2
let quanitytUnit = HKUnit(from: “fl_oz_us”)
let quantityAmount = HKQuantity(unit: quanitytUnit, doubleValue: ounces) let now = Date() // 3
let sample = HKQuantitySample(type: quantityType!, quantity: quantityAmount, start: now, end: now)
let correlationType = HKObjectType.correlationType(forIdentifier: HKCorrelationTypeIdentifier.food) // 4
let waterCorrelationForWaterAmount = HKCorrelation(type: correlationType!, start: now, end: now, objects: [sample])
// Send water intake data to healthStore…aka ‘Health’ app // 5
self.healthStore?.save(waterCorrelationForWaterAmount, withCompletion: { (success, error) in
if (error != nil) {
NSLog(“error occurred saving water data”)
}
})
}

5. The best way to break down this method is to start at the end of it. We need to call save() on the healthStore reference. Save takes a HKCorrelation and a completion handler as parameters. You can see this listed 5.

4 . We initalize an HKCorrelation called “waterCorrelationForWaterAmount.” In order to create an HKCorrelation, we need a HKObjectType, a start Date, an end Date, and a set of HKSamples.

3. To make our HKQuantitySample, we need a HKQuantityType (defined in 1), a HKQuantityAmount (defined in 2), and a start and end Date. Here we also make our correlationType equal to a food correlation, meaning, the user is interacting with this data by literally consuming it like it’s food (even though it’s acutally water) .

2. To create our HKQuantity, we need a unit of measurement for our quantity. We initialize a HKUnit representign US fluid Ounces. Now we take our passed in parameter ounces, along with our unit value, and create a HKQuantity.

  1. We need to know the type of Quantity 2 we’re representign. So we initialize our quantityType to be dietaryWater. Meaning, we’re tracking the intake of water being consumed in our diet.

Now that we have our quantityType, we can create our sample, based off of our quantityAmount and quantityType, and our start and end date which should be right now. We can finish the initialization of our HKCorrelation in 4, by adding in our correlationType, our dates, and our Set of samples (which is just the one sample).

Getting back to 5, we pass in this correlation and the data is sent to the healthStore object and saved into the Health App. You can build and run your project, call addWaterDataToHealthStore() with an amount of water. Now switch over to your health app and view for yourself!

--

--