Channels ▼
RSS

Mobile

iOS 8 HealthKit: Working with Biometric Data


Apple's recently released iOS 8 introduced a new Health app that provides iPhone users access to a dashboard of health and fitness data. The HealthKit framework included in the iOS SDK 8 allows app developers to request permissions from the users themselves to read and write specific types of health and fitness data. The framework makes it possible to ask for, create, and save health and fitness data that the users will see summarized in the Health app. In this article, I explain how to work with the HealthKit framework in Swift to request the necessary permissions, write and retrieve health and fitness data, and to perform needed unit conversions.

Working with Units and Quantities in the Playground

At the time of writing, the Health app is available only for iPhone, so you cannot use the HealthKit framework in iPad or iPod apps. Before you continue reading this article, I suggest you to take a look at the new Health app in either an iPhone with iOS 8.02 or the iPhone Simulator.

One of the main problems you have when you want to write and query health and fitness data in an iPhone is that you will be working with data that is extremely sensitive for the user. Thus, the HealthKit API requires you to request specific permissions from the user to read and write the different types of health and fitness data before you can perform these operations. For example, if your app wants to write body temperature data and read the user's registered date of birth, height, and weight, the app must ask the user to allow your app to perform the following four actions:

  • Write Body Temperature
  • Read Date of Birth
  • Read Height
  • Read Weight

Once the user has allowed your app to perform each listed action, the app will appear listed as a source in the Sources page of the Health app. The user can review the operations allowed to your specific app by tapping on the app name and can decide to make changes to the permitted read and write operations. You just need to make some specific API calls to make sure that you have the necessary permissions to perform the operations required for your app.

When you store and query health and fitness data, there is another big problem to solve: the units in which the values are expressed, their conversions, and localizations. For example, imagine an app that stores body temperature data without considering units and their conversions. A value of 39 degrees Celsius (equivalent to 102.2 degrees Fahrenheit) in an adult would mean that your body temperature is higher than normal (fever). However, a value of 39 degrees Fahrenheit (equivalent to 3.88 degrees Celsius) would mean your body is close to its freezing point. If your app just stores values without considering the related units and the user preferences, you can have huge mistakes. If the app just saves 39 degrees and thinks that the user will always display Celsius, it will still display 39 degrees to a user whose settings use Fahrenheit as the default temperature unit. Thus, the app will provide wrong information to the user.

The data in HealthKit is always represented by a double value with an associated simple or complex unit. The units are classified into types and it is possible to check the compatibility between units before performing conversions. Thus, the most important thing to learn before you start working with the HealthKit framework is the way it works with quantities and units. You can work with HealthKit quantities and units in the Swift interactive Playground introduced with XCode 6. Later, it will be necessary to work in an actual project because the Playground doesn't allow you to interact with the HealthKit data store — you will need to run code in either the iPhone simulator or in an iPhone device.

Start XCode, select File | New | Playground…, enter a name for the Playground, select iOS as the desired platform, click Next, select the desired location for the Playground file, and click Create. XCode will display a Playground window with a line that imports UIKit and creates a string variable. You just need to add the following line to be able to work with quantities and units from the HealthKit framework:

import HealthKit

All HealthKit types start with the HK prefix. HKUnit represents a particular unit that can be either simple or complex. Simple units for Temperature are degrees Celsius and degrees Fahrenheit. A complex unit for Mass / Volume is ounces per liter (oz/L). HKUnit supports many standard SI units (short for Système Internationale d'Unités in French — equivalent to International System of Units in English) and non-SI units. You can take a look at the HKUnit.h header within the Healthkit.framework to check the available units, the string representations accepted by HKUnit, and the available prefixes. If you add the following two lines to the Swift Playground, when you check the results at the right hand side of the window, you will notice they generate instances of HKTemperatureUnit.

let degCUnit = HKUnit.degreeCelsiusUnit()
let degFUnit = HKUnit.degreeFahrenheitUnit()

It is also possible to use the HKUnit initializer, which returns the appropriate unit instance from its string representation. For example, the following lines also generate instances of HKTemperatureUnit for degrees in Celsius and Fahrenheit:

let degCUnitFromStr = HKUnit(fromString: "degC")
let degFUnitFromStr = HKUnit(fromString: "degF")

The following lines generate two instances of HKEnergyUnit, one for kiloCalories and the other for kiloJoules.

let kiloCaloriesUnit = HKUnit(fromString: "kcal")
let joulesUnit = HKUnit(fromString: "kJ")

The next two lines generate two instances of HKMassUnit, one for kilograms and the other for pounds.

let kiloGramsUnit = HKUnit.gramUnitWithMetricPrefix(HKMetricPrefix.Kilo)
let poundsUnit = HKUnit.poundUnit()

The next line generates an instance of _HKCompoundUnit because the string specifies a complex unit for Mass / Volume: ounces per liter (oz/L).

let ouncesPerLiter = HKUnit(fromString: "oz/L")

HKQuantity encapsulates a quantity value (Double) and the unit of measurement (HKUnit). This class doesn't provide all the operations you might expect to work with quantities and their units of measure, but it allows you to perform some useful compatibility checks and conversions. The following lines create two HKQuantity instances with temperature units: bodyTemperature1 and bodyTemperature2. The former uses degrees Celsius (degCUnit) and the latter degrees Fahrenheit (degFUnit). Then, the code calls the isCompatibleWithUnit method to make sure that each HKQuantity instance can be converted to degrees Fahrenheit (degFUnit). If isCompatibleWithUnit returns true, it means that you can convert to the HKUnit specified as an argument. You always have to call this method before calling the doubleValueForUnit method. This way, you will avoid errors when units aren't compatible. The doubleValueForUnit method returns the quantity value converted to the unit specified as an argument. In this case, the two calls make sure that the value is expressed in degrees Fahrenheit no matter the temperature unit specified in each HKQuantity instance.

let bodyTemperature1 = HKQuantity(unit: degCUnit, doubleValue: 35.2)
let bodyTemperature2 = HKQuantity(unit: degFUnit, doubleValue: 95)
println(bodyTemperature1.description)
println(bodyTemperature2.description)

if bodyTemperature1.isCompatibleWithUnit(degFUnit) {
    println("Temperature #1 in Fahrenheit degrees:
\(bodyTemperature1.doubleValueForUnit(degFUnit))")
}

if bodyTemperature2.isCompatibleWithUnit(degFUnit) {
    println("Temperature #2 in Fahrenheit degrees: \(bodyTemperature2.doubleValueForUnit(degFUnit))")
}

The following line shows an example of code that creates a new HKQuantity instance with a quantity and temperature unit converted from degrees Fahrenheit to degrees Celsius. There is no convert method that acts as a shortcut, so you have to call doubleValueForUnit and use it in the HKQuantity initializer.

let bodyTemperature2InDegC = HKQuantity(unit: degCUnit, doubleValue: bodyTemperature2.doubleValueForUnit(degCUnit))

The compare method returns an NSComparisonResult value that indicates whether the receiver is greater than, equal to, or less than the compatible HKQuantity specified as an argument. For example, the following lines compare bodyTemperature1 with bodyTemperature2 and print the results of the comparison. Notice that it isn't necessary to convert both HKQuantity instances to the same unit, they just need to be compatible and the compare method will be able to perform the comparison making the necessary conversions under the hood. In this case, one of the temperatures is in degrees Celsius and the other in degrees Fahrenheit.

let comparisonResult = bodyTemperature1.compare(bodyTemperature2)
switch comparisonResult {
    case NSComparisonResult.OrderedDescending:
        println("Temperature #1 is greater than #2")
    case NSComparisonResult.OrderedAscending:
        println("Temperature #2 is greater than #1")
    case NSComparisonResult.OrderedSame:
        println("Temperature #1 is equal to Temperature #2")
}

Requesting Permissions to Read and Write Data

Now that we've looked at the basics of quantities and units in the HealthKit framework, we can start reading and writing health and fitness data. Create a new iOS Application in XCode 6.01 or later, use the Single View Application template, select iPhone as the target device, and Swift as the language. This template allows me to add some code in a view controller and stay focused on the HealthKit framework to provide a simple example. From here, you can develop a nice UI that uses the HealthKit framework.

Go to the App Capabilities in XCode and activate HealthKit. Notice that you need an iOS Developer Program membership to successfully enable HealthKit capability.  When you turn on HealthKit, XCode performs the following actions (see Figure 1):

  • Add the HealthKit entitlement to the App ID.
  • Add the HealthKit key to the info.plist file.
  • Add the HealthKit entitlement to the .entitlements file.
  • Link HealthKit.framework.

HealthKit
Figure 1: After you enable the HealthKit capability, the project links the HealthKit.framework.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.